blob: 39a64cf26da79e599fc36b92b0b417f2b76c96a2 [file] [log] [blame]
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGraphics.h"
5#include "SkRandom.h"
6
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +00007static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
8 SkPaint p;
9
10 p.setAntiAlias(true);
11 p.setStyle(SkPaint::kStroke_Style);
12 p.setStrokeWidth(4);
13
14 canvas->drawRect(r, p);
15
16 SkPath path;
17 SkRect r2(r);
18 r2.offset(18, 0);
19 path.addRect(r2);
20
21 canvas->drawPath(path, p);
22}
23
24static void test_strokerect(SkCanvas* canvas) {
25 canvas->drawColor(SK_ColorWHITE);
26
27 SkRect r;
28
29 r.set(10, 10, 14, 14);
reed@google.com261b8e22011-04-14 17:53:24 +000030 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000031 test_strokerect(canvas, r);
32 canvas->translate(0, 20);
33
34 r.set(10, 10, 14.5f, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000035 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000036 test_strokerect(canvas, r);
37 canvas->translate(0, 20);
38
39 r.set(10, 10, 14.5f, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000040 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000041 test_strokerect(canvas, r);
42 canvas->translate(0, 20);
43
44 r.set(10, 10, 20, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000045 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000046 test_strokerect(canvas, r);
47 canvas->translate(0, 20);
48
49 r.set(10, 10, 20, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000050 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000051 test_strokerect(canvas, r);
52 canvas->translate(0, 20);
53
54}
55
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000056class Draw : public SkRefCnt {
57public:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000058 Draw() : fFlags(0) {}
59
60 enum Flags {
61 kSelected_Flag = 1 << 0
62 };
63 int getFlags() const { return fFlags; }
64 void setFlags(int flags);
65
66 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
67 void setSelected(bool pred) {
68 if (pred) {
69 fFlags |= kSelected_Flag;
70 } else {
71 fFlags &= ~kSelected_Flag;
72 }
73 }
74
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000075 void draw(SkCanvas* canvas) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000076 int sc = canvas->save();
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000077 this->onDraw(canvas);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000078 canvas->restoreToCount(sc);
79
80 if (this->isSelected()) {
81 this->drawSelection(canvas);
82 }
83 }
84
85 void drawSelection(SkCanvas* canvas) {
86 int sc = canvas->save();
87 this->onDrawSelection(canvas);
88 canvas->restoreToCount(sc);
89 }
90
91 void getBounds(SkRect* bounds) {
92 this->onGetBounds(bounds);
93 }
94
95 bool hitTest(SkScalar x, SkScalar y) {
96 return this->onHitTest(x, y);
97 }
98
99 void offset(SkScalar dx, SkScalar dy) {
100 if (dx || dy) {
101 this->onOffset(dx, dy);
102 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000103 }
104
105protected:
106 virtual void onDraw(SkCanvas*) = 0;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000107 virtual void onGetBounds(SkRect*) = 0;
108 virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
109 virtual void onDrawSelection(SkCanvas* canvas) {
110 SkRect r;
111 this->getBounds(&r);
112 SkPaint paint;
113 SkPoint pts[4];
114 r.toQuad(pts);
115 paint.setStrokeWidth(SkIntToScalar(10));
116 paint.setColor(0x80FF8844);
117 paint.setStrokeCap(SkPaint::kRound_Cap);
118 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
119 }
120 virtual bool onHitTest(SkScalar x, SkScalar y) {
121 SkRect bounds;
122 this->getBounds(&bounds);
123 return bounds.contains(x, y);
124 }
125
126private:
127 int fFlags;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000128};
129
130class RDraw : public Draw {
131public:
132 enum Style {
133 kRect_Style,
134 kOval_Style,
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000135 kRRect_Style,
136 kFrame_Style
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000137 };
138
139 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
140
141 void setRect(const SkRect& r) {
142 fRect = r;
143 }
144
145 void setPaint(const SkPaint& p) {
146 fPaint = p;
147 }
148
149protected:
150 virtual void onDraw(SkCanvas* canvas) {
151 switch (fStyle) {
152 case kRect_Style:
153 canvas->drawRect(fRect, fPaint);
154 break;
155 case kOval_Style:
156 canvas->drawOval(fRect, fPaint);
157 break;
158 case kRRect_Style: {
159 SkScalar rx = fRect.width() / 5;
160 SkScalar ry = fRect.height() / 5;
161 if (rx < ry) {
162 ry = rx;
163 } else {
164 rx = ry;
165 }
166 canvas->drawRoundRect(fRect, rx, ry, fPaint);
167 break;
168 }
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000169 case kFrame_Style: {
170 SkPath path;
171 path.addOval(fRect, SkPath::kCW_Direction);
172 SkRect r = fRect;
173 r.inset(fRect.width()/6, 0);
174 path.addOval(r, SkPath::kCCW_Direction);
175 canvas->drawPath(path, fPaint);
176 break;
177 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000178 }
179 }
180
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000181 virtual void onGetBounds(SkRect* bounds) {
182 *bounds = fRect;
183 }
184
185 virtual void onOffset(SkScalar dx, SkScalar dy) {
186 fRect.offset(dx, dy);
187 }
188
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000189private:
190 SkRect fRect;
191 SkPaint fPaint;
192 Style fStyle;
193};
194
195class DrawFactory {
196public:
197 DrawFactory() {
198 fPaint.setAntiAlias(true);
199 }
200
201 const SkPaint& getPaint() const { return fPaint; }
202
203 void setPaint(const SkPaint& p) {
204 fPaint = p;
205 }
206
207 virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
208
209private:
210 SkPaint fPaint;
211};
212
213class RectFactory : public DrawFactory {
214public:
215 virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
216 SkRect r;
217 r.set(p0.x(), p0.y(), p1.x(), p1.y());
218 r.sort();
219
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000220// RDraw* d = new RDraw(r, RDraw::kRRect_Style);
221 RDraw* d = new RDraw(r, RDraw::kFrame_Style);
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000222 d->setPaint(this->getPaint());
223 return d;
224 }
225};
226
227class DrawView : public SkView {
228 Draw* fDraw;
229 DrawFactory* fFactory;
230 SkRandom fRand;
231 SkTDArray<Draw*> fList;
232
233public:
234 DrawView() : fDraw(NULL) {
235 fFactory = new RectFactory;
236 }
237
238 virtual ~DrawView() {
239 fList.unrefAll();
240 SkSafeUnref(fDraw);
241 }
242
243 Draw* setDraw(Draw* d) {
244 SkRefCnt_SafeAssign(fDraw, d);
245 return d;
246 }
247
248 SkColor randColor() {
249 return (SkColor)fRand.nextU() | 0xFF000000;
250 }
251
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000252 Draw* hitTestList(SkScalar x, SkScalar y) const {
253 Draw** first = fList.begin();
254 for (Draw** iter = fList.end(); iter > first;) {
255 --iter;
256 if ((*iter)->hitTest(x, y)) {
257 return *iter;
258 }
259 }
260 return NULL;
261 }
262
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000263protected:
264 // overrides from SkEventSink
265 virtual bool onQuery(SkEvent* evt) {
266 if (SampleCode::TitleQ(*evt)) {
267 SampleCode::TitleR(evt, "Draw");
268 return true;
269 }
270 return this->INHERITED::onQuery(evt);
271 }
272
273 void drawBG(SkCanvas* canvas) {
274 canvas->drawColor(0xFFDDDDDD);
275// canvas->drawColor(SK_ColorWHITE);
276 }
277
278 virtual void onDraw(SkCanvas* canvas) {
279 this->drawBG(canvas);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000280 // test_strokerect(canvas);
281 // return;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000282
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000283 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000284 (*iter)->draw(canvas);
285 }
286 if (fDraw) {
287 fDraw->draw(canvas);
288 }
289 }
290
291 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000292 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
293 (*iter)->setSelected(false);
294 }
295
296 Click* c = new Click(this);
297 Draw* d = this->hitTestList(x, y);
298 if (d) {
299 d->setSelected(true);
300 c->setType("dragger");
301 } else {
302 c->setType("maker");
303 }
304 return c;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000305 }
306
307 virtual bool onClick(Click* click) {
308 if (Click::kUp_State == click->fState) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000309 if (click->isType("maker")) {
310 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
311 *fList.append() = fDraw;
312 } else {
313 fDraw->unref();
314 }
315 fDraw = NULL;
316 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000317 return true;
318 }
319
320 if (Click::kDown_State == click->fState) {
321 SkPaint p = fFactory->getPaint();
322 p.setColor(this->randColor());
323 fFactory->setPaint(p);
324 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000325
326 if (click->isType("maker")) {
327 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
328 } else if (click->isType("dragger")) {
329 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
330 if ((*iter)->isSelected()) {
331 (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
332 click->fCurr.y() - click->fPrev.y());
333 }
334 }
335 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000336 this->inval(NULL);
337 return true;
338 }
339
340private:
341 typedef SkView INHERITED;
342};
343
344//////////////////////////////////////////////////////////////////////////////
345
346static SkView* MyFactory() { return new DrawView; }
347static SkViewRegister reg(MyFactory);
348