blob: 776d6daa4d123a4f4ac09ab91d3458eb007aa712 [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
7class Draw : public SkRefCnt {
8public:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00009 Draw() : fFlags(0) {}
10
11 enum Flags {
12 kSelected_Flag = 1 << 0
13 };
14 int getFlags() const { return fFlags; }
15 void setFlags(int flags);
16
17 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
18 void setSelected(bool pred) {
19 if (pred) {
20 fFlags |= kSelected_Flag;
21 } else {
22 fFlags &= ~kSelected_Flag;
23 }
24 }
25
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000026 void draw(SkCanvas* canvas) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000027 int sc = canvas->save();
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000028 this->onDraw(canvas);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000029 canvas->restoreToCount(sc);
30
31 if (this->isSelected()) {
32 this->drawSelection(canvas);
33 }
34 }
35
36 void drawSelection(SkCanvas* canvas) {
37 int sc = canvas->save();
38 this->onDrawSelection(canvas);
39 canvas->restoreToCount(sc);
40 }
41
42 void getBounds(SkRect* bounds) {
43 this->onGetBounds(bounds);
44 }
45
46 bool hitTest(SkScalar x, SkScalar y) {
47 return this->onHitTest(x, y);
48 }
49
50 void offset(SkScalar dx, SkScalar dy) {
51 if (dx || dy) {
52 this->onOffset(dx, dy);
53 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000054 }
55
56protected:
57 virtual void onDraw(SkCanvas*) = 0;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000058 virtual void onGetBounds(SkRect*) = 0;
59 virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
60 virtual void onDrawSelection(SkCanvas* canvas) {
61 SkRect r;
62 this->getBounds(&r);
63 SkPaint paint;
64 SkPoint pts[4];
65 r.toQuad(pts);
66 paint.setStrokeWidth(SkIntToScalar(10));
67 paint.setColor(0x80FF8844);
68 paint.setStrokeCap(SkPaint::kRound_Cap);
69 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
70 }
71 virtual bool onHitTest(SkScalar x, SkScalar y) {
72 SkRect bounds;
73 this->getBounds(&bounds);
74 return bounds.contains(x, y);
75 }
76
77private:
78 int fFlags;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000079};
80
81class RDraw : public Draw {
82public:
83 enum Style {
84 kRect_Style,
85 kOval_Style,
86 kRRect_Style
87 };
88
89 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
90
91 void setRect(const SkRect& r) {
92 fRect = r;
93 }
94
95 void setPaint(const SkPaint& p) {
96 fPaint = p;
97 }
98
99protected:
100 virtual void onDraw(SkCanvas* canvas) {
101 switch (fStyle) {
102 case kRect_Style:
103 canvas->drawRect(fRect, fPaint);
104 break;
105 case kOval_Style:
106 canvas->drawOval(fRect, fPaint);
107 break;
108 case kRRect_Style: {
109 SkScalar rx = fRect.width() / 5;
110 SkScalar ry = fRect.height() / 5;
111 if (rx < ry) {
112 ry = rx;
113 } else {
114 rx = ry;
115 }
116 canvas->drawRoundRect(fRect, rx, ry, fPaint);
117 break;
118 }
119 }
120 }
121
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000122 virtual void onGetBounds(SkRect* bounds) {
123 *bounds = fRect;
124 }
125
126 virtual void onOffset(SkScalar dx, SkScalar dy) {
127 fRect.offset(dx, dy);
128 }
129
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000130private:
131 SkRect fRect;
132 SkPaint fPaint;
133 Style fStyle;
134};
135
136class DrawFactory {
137public:
138 DrawFactory() {
139 fPaint.setAntiAlias(true);
140 }
141
142 const SkPaint& getPaint() const { return fPaint; }
143
144 void setPaint(const SkPaint& p) {
145 fPaint = p;
146 }
147
148 virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
149
150private:
151 SkPaint fPaint;
152};
153
154class RectFactory : public DrawFactory {
155public:
156 virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
157 SkRect r;
158 r.set(p0.x(), p0.y(), p1.x(), p1.y());
159 r.sort();
160
161 RDraw* d = new RDraw(r, RDraw::kRRect_Style);
162 d->setPaint(this->getPaint());
163 return d;
164 }
165};
166
167class DrawView : public SkView {
168 Draw* fDraw;
169 DrawFactory* fFactory;
170 SkRandom fRand;
171 SkTDArray<Draw*> fList;
172
173public:
174 DrawView() : fDraw(NULL) {
175 fFactory = new RectFactory;
176 }
177
178 virtual ~DrawView() {
179 fList.unrefAll();
180 SkSafeUnref(fDraw);
181 }
182
183 Draw* setDraw(Draw* d) {
184 SkRefCnt_SafeAssign(fDraw, d);
185 return d;
186 }
187
188 SkColor randColor() {
189 return (SkColor)fRand.nextU() | 0xFF000000;
190 }
191
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000192 Draw* hitTestList(SkScalar x, SkScalar y) const {
193 Draw** first = fList.begin();
194 for (Draw** iter = fList.end(); iter > first;) {
195 --iter;
196 if ((*iter)->hitTest(x, y)) {
197 return *iter;
198 }
199 }
200 return NULL;
201 }
202
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000203protected:
204 // overrides from SkEventSink
205 virtual bool onQuery(SkEvent* evt) {
206 if (SampleCode::TitleQ(*evt)) {
207 SampleCode::TitleR(evt, "Draw");
208 return true;
209 }
210 return this->INHERITED::onQuery(evt);
211 }
212
213 void drawBG(SkCanvas* canvas) {
214 canvas->drawColor(0xFFDDDDDD);
215// canvas->drawColor(SK_ColorWHITE);
216 }
217
218 virtual void onDraw(SkCanvas* canvas) {
219 this->drawBG(canvas);
220
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000221 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000222 (*iter)->draw(canvas);
223 }
224 if (fDraw) {
225 fDraw->draw(canvas);
226 }
227 }
228
229 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000230 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
231 (*iter)->setSelected(false);
232 }
233
234 Click* c = new Click(this);
235 Draw* d = this->hitTestList(x, y);
236 if (d) {
237 d->setSelected(true);
238 c->setType("dragger");
239 } else {
240 c->setType("maker");
241 }
242 return c;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000243 }
244
245 virtual bool onClick(Click* click) {
246 if (Click::kUp_State == click->fState) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000247 if (click->isType("maker")) {
248 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
249 *fList.append() = fDraw;
250 } else {
251 fDraw->unref();
252 }
253 fDraw = NULL;
254 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000255 return true;
256 }
257
258 if (Click::kDown_State == click->fState) {
259 SkPaint p = fFactory->getPaint();
260 p.setColor(this->randColor());
261 fFactory->setPaint(p);
262 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000263
264 if (click->isType("maker")) {
265 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
266 } else if (click->isType("dragger")) {
267 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
268 if ((*iter)->isSelected()) {
269 (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
270 click->fCurr.y() - click->fPrev.y());
271 }
272 }
273 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000274 this->inval(NULL);
275 return true;
276 }
277
278private:
279 typedef SkView INHERITED;
280};
281
282//////////////////////////////////////////////////////////////////////////////
283
284static SkView* MyFactory() { return new DrawView; }
285static SkViewRegister reg(MyFactory);
286