allow window-subclass to handle dispatching click events (for resize)
add drag tracking to Draw
git-svn-id: http://skia.googlecode.com/svn/trunk@967 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 3a7a1a6..bb55da3 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -13,6 +13,7 @@
#include "GrContext.h"
#include "SkTouchGesture.h"
+#define USE_ARROWS_FOR_ZOOM true
//#define DEFAULT_TO_GPU
extern SkView* create_overview(int, const SkViewFactory[]);
@@ -122,6 +123,9 @@
//////////////////////////////////////////////////////////////////////////////
+#define MAX_ZOOM_LEVEL 8
+#define MIN_ZOOM_LEVEL -8
+
static const char gCharEvtName[] = "SampleCode_Char_Event";
static const char gKeyEvtName[] = "SampleCode_Key_Event";
static const char gTitleEvtName[] = "SampleCode_Title_Event";
@@ -225,6 +229,7 @@
virtual bool onEvent(const SkEvent& evt);
virtual bool onQuery(SkEvent* evt);
+ virtual bool onDispatchClick(int x, int y, Click::State);
virtual bool onClick(Click* click);
virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
@@ -233,9 +238,6 @@
virtual bool handleEvent(const SkEvent& evt);
virtual bool handleKey(SkKey key);
virtual bool handleKeyUp(SkKey key);
-
- virtual bool onClick(Click* click);
- virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
virtual bool onHandleKeyUp(SkKey key);
#endif
@@ -248,6 +250,8 @@
SkPath fClipPath;
SkTouchGesture fGesture;
+ int fZoomLevel;
+ SkScalar fZoomScale;
enum CanvasType {
kRaster_CanvasType,
@@ -269,6 +273,7 @@
int fScrollTestX, fScrollTestY;
bool make3DReady();
+ void changeZoomLevel(int delta);
void loadView(SkView*);
void updateTitle();
@@ -340,6 +345,9 @@
fLCDMode = LCDTextDrawFilter::kNeutral_Mode;
fScrollTestX = fScrollTestY = 0;
+ fZoomLevel = 0;
+ fZoomScale = SK_Scalar1;
+
// this->setConfig(SkBitmap::kRGB_565_Config);
this->setConfig(SkBitmap::kARGB_8888_Config);
this->setVisibleP(true);
@@ -401,6 +409,23 @@
gAnimTimePrev = gAnimTime;
gAnimTime = SkTime::GetMSecs();
+ if (fZoomLevel) {
+ SkMatrix m;
+ SkScalar cx = SkScalarHalf(this->width());
+ SkScalar cy = SkScalarHalf(this->height());
+ SkPoint center;
+ m = canvas->getTotalMatrix();//.invert(&m);
+ m.mapXY(cx, cy, ¢er);
+ cx = center.fX;
+ cy = center.fY;
+
+ m.setTranslate(-cx, -cy);
+ m.postScale(fZoomScale, fZoomScale);
+ m.postTranslate(cx, cy);
+
+ canvas->concat(m);
+ }
+
// Apply any gesture matrix
if (true) {
const SkMatrix& localM = fGesture.localM();
@@ -506,6 +531,8 @@
bitmap.width(), bitmap.height(),
false, false);
fGpuCanvas->setDevice(device)->unref();
+
+ fGpuCanvas->concat(canvas->getTotalMatrix());
canvas = fGpuCanvas;
} else {
@@ -640,6 +667,21 @@
return gConfigCycle[c];
}
+void SampleWindow::changeZoomLevel(int delta) {
+ fZoomLevel += delta;
+ if (fZoomLevel > 0) {
+ fZoomLevel = SkMin32(fZoomLevel, MAX_ZOOM_LEVEL);
+ fZoomScale = SkIntToScalar(fZoomLevel + 1);
+ } else if (fZoomLevel < 0) {
+ fZoomLevel = SkMax32(fZoomLevel, MIN_ZOOM_LEVEL);
+ fZoomScale = SK_Scalar1 / (1 - fZoomLevel);
+ } else {
+ fZoomScale = SK_Scalar1;
+ }
+
+ this->inval(NULL);
+}
+
bool SampleWindow::nextSample() {
fCurrIndex = (fCurrIndex + 1) % fSamples.count();
this->loadView(fSamples[fCurrIndex]());
@@ -816,12 +858,20 @@
this->inval(NULL);
return true;
case kUp_SkKey:
- fNClip = !fNClip;
+ if (USE_ARROWS_FOR_ZOOM) {
+ this->changeZoomLevel(1);
+ } else {
+ fNClip = !fNClip;
+ this->inval(NULL);
+ }
this->updateTitle();
- this->inval(NULL);
return true;
case kDown_SkKey:
- this->setConfig(cycle_configs(this->getBitmap().config()));
+ if (USE_ARROWS_FOR_ZOOM) {
+ this->changeZoomLevel(-1);
+ } else {
+ this->setConfig(cycle_configs(this->getBitmap().config()));
+ }
this->updateTitle();
return true;
case kOK_SkKey:
@@ -849,6 +899,18 @@
static const char gGestureClickType[] = "GestureClickType";
+bool SampleWindow::onDispatchClick(int x, int y, Click::State state) {
+ int w = SkScalarRound(this->width());
+ int h = SkScalarRound(this->height());
+
+ // check for the resize-box
+ if (w - x < 16 && h - y < 16) {
+ return false; // let the OS handle the click
+ } else {
+ return this->INHERITED::onDispatchClick(x, y, state);
+ }
+}
+
class GestureClick : public SkView::Click {
public:
GestureClick(SkView* target) : SkView::Click(target) {
@@ -961,6 +1023,10 @@
} else if (LCDTextDrawFilter::kForceOff_Mode == fLCDMode) {
title.prepend("lcd ");
}
+
+ if (fZoomLevel) {
+ title.prependf("{%d} ", fZoomLevel);
+ }
this->setTitle(title.c_str());
}
diff --git a/samplecode/SampleDraw.cpp b/samplecode/SampleDraw.cpp
index d7e8dce..776d6da 100644
--- a/samplecode/SampleDraw.cpp
+++ b/samplecode/SampleDraw.cpp
@@ -6,12 +6,76 @@
class Draw : public SkRefCnt {
public:
+ Draw() : fFlags(0) {}
+
+ enum Flags {
+ kSelected_Flag = 1 << 0
+ };
+ int getFlags() const { return fFlags; }
+ void setFlags(int flags);
+
+ bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
+ void setSelected(bool pred) {
+ if (pred) {
+ fFlags |= kSelected_Flag;
+ } else {
+ fFlags &= ~kSelected_Flag;
+ }
+ }
+
void draw(SkCanvas* canvas) {
+ int sc = canvas->save();
this->onDraw(canvas);
+ canvas->restoreToCount(sc);
+
+ if (this->isSelected()) {
+ this->drawSelection(canvas);
+ }
+ }
+
+ void drawSelection(SkCanvas* canvas) {
+ int sc = canvas->save();
+ this->onDrawSelection(canvas);
+ canvas->restoreToCount(sc);
+ }
+
+ void getBounds(SkRect* bounds) {
+ this->onGetBounds(bounds);
+ }
+
+ bool hitTest(SkScalar x, SkScalar y) {
+ return this->onHitTest(x, y);
+ }
+
+ void offset(SkScalar dx, SkScalar dy) {
+ if (dx || dy) {
+ this->onOffset(dx, dy);
+ }
}
protected:
virtual void onDraw(SkCanvas*) = 0;
+ virtual void onGetBounds(SkRect*) = 0;
+ virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
+ virtual void onDrawSelection(SkCanvas* canvas) {
+ SkRect r;
+ this->getBounds(&r);
+ SkPaint paint;
+ SkPoint pts[4];
+ r.toQuad(pts);
+ paint.setStrokeWidth(SkIntToScalar(10));
+ paint.setColor(0x80FF8844);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
+ }
+ virtual bool onHitTest(SkScalar x, SkScalar y) {
+ SkRect bounds;
+ this->getBounds(&bounds);
+ return bounds.contains(x, y);
+ }
+
+private:
+ int fFlags;
};
class RDraw : public Draw {
@@ -55,6 +119,14 @@
}
}
+ virtual void onGetBounds(SkRect* bounds) {
+ *bounds = fRect;
+ }
+
+ virtual void onOffset(SkScalar dx, SkScalar dy) {
+ fRect.offset(dx, dy);
+ }
+
private:
SkRect fRect;
SkPaint fPaint;
@@ -117,6 +189,17 @@
return (SkColor)fRand.nextU() | 0xFF000000;
}
+ Draw* hitTestList(SkScalar x, SkScalar y) const {
+ Draw** first = fList.begin();
+ for (Draw** iter = fList.end(); iter > first;) {
+ --iter;
+ if ((*iter)->hitTest(x, y)) {
+ return *iter;
+ }
+ }
+ return NULL;
+ }
+
protected:
// overrides from SkEventSink
virtual bool onQuery(SkEvent* evt) {
@@ -135,9 +218,7 @@
virtual void onDraw(SkCanvas* canvas) {
this->drawBG(canvas);
- Draw** iter = fList.begin();
- Draw** stop = fList.end();
- for (; iter < stop; iter++) {
+ for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
(*iter)->draw(canvas);
}
if (fDraw) {
@@ -146,13 +227,31 @@
}
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
- return new Click(this);
+ for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
+ (*iter)->setSelected(false);
+ }
+
+ Click* c = new Click(this);
+ Draw* d = this->hitTestList(x, y);
+ if (d) {
+ d->setSelected(true);
+ c->setType("dragger");
+ } else {
+ c->setType("maker");
+ }
+ return c;
}
virtual bool onClick(Click* click) {
if (Click::kUp_State == click->fState) {
- *fList.append() = fDraw;
- fDraw = NULL;
+ if (click->isType("maker")) {
+ if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
+ *fList.append() = fDraw;
+ } else {
+ fDraw->unref();
+ }
+ fDraw = NULL;
+ }
return true;
}
@@ -161,7 +260,17 @@
p.setColor(this->randColor());
fFactory->setPaint(p);
}
- this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
+
+ if (click->isType("maker")) {
+ this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
+ } else if (click->isType("dragger")) {
+ for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
+ if ((*iter)->isSelected()) {
+ (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
+ click->fCurr.y() - click->fPrev.y());
+ }
+ }
+ }
this->inval(NULL);
return true;
}