SampleDraw.cpp revision dd0cd34067d103ace7c6739405cb7885d8ad3fb2
1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "SampleCode.h" 2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "SkView.h" 3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "SkCanvas.h" 4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "SkGraphics.h" 5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "SkRandom.h" 6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass Draw : public SkRefCnt { 8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangpublic: 9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang Draw() : fFlags(0) {} 10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang enum Flags { 12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang kSelected_Flag = 1 << 0 13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang }; 14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int getFlags() const { return fFlags; } 15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang void setFlags(int flags); 16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 17ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); } 18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang void setSelected(bool pred) { 19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (pred) { 20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang fFlags |= kSelected_Flag; 21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } else { 22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang fFlags &= ~kSelected_Flag; 23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang void draw(SkCanvas* canvas) { 27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int sc = canvas->save(); 28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang this->onDraw(canvas); 29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang canvas->restoreToCount(sc); 30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 31ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (this->isSelected()) { 32ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang this->drawSelection(canvas); 33ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 34ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 35ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang void drawSelection(SkCanvas* canvas) { 37ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int sc = canvas->save(); 38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang this->onDrawSelection(canvas); 39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang canvas->restoreToCount(sc); 40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 41ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang void getBounds(SkRect* bounds) { 43ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang this->onGetBounds(bounds); 44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 46ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang bool hitTest(SkScalar x, SkScalar y) { 47ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return this->onHitTest(x, y); 48ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 49ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 50ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang void offset(SkScalar dx, SkScalar dy) { 51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (dx || dy) { 52ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang this->onOffset(dx, dy); 53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 54ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 55ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 56ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangprotected: 57ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang virtual void onDraw(SkCanvas*) = 0; 58ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 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; 79}; 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 122 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 130private: 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 192 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 203protected: 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 221 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { 222 (*iter)->draw(canvas); 223 } 224 if (fDraw) { 225 fDraw->draw(canvas); 226 } 227 } 228 229 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { 230 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; 243 } 244 245 virtual bool onClick(Click* click) { 246 if (Click::kUp_State == click->fState) { 247 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 } 255 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 } 263 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 } 274 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 287