allow window-subclass to handle dispatching click events (for resize)
authormike@reedtribe.org <mike@reedtribe.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 21 Mar 2011 00:53:39 +0000 (00:53 +0000)
committermike@reedtribe.org <mike@reedtribe.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 21 Mar 2011 00:53:39 +0000 (00:53 +0000)
add drag tracking to Draw

git-svn-id: http://skia.googlecode.com/svn/trunk@967 2bbb7eff-a529-9590-31e7-b0007b416f81

include/views/SkWindow.h
samplecode/SampleApp.cpp
samplecode/SampleDraw.cpp
src/views/SkWindow.cpp

index ffba275..7b37779 100644 (file)
@@ -72,7 +72,7 @@ public:
 
 protected:
     virtual bool onEvent(const SkEvent&);
-
+    virtual bool onDispatchClick(int x, int y, Click::State);
     // called if part of our bitmap is invalidated
     virtual void onHandleInval(const SkIRect&);
     virtual bool onHandleChar(SkUnichar);
index 3a7a1a6..bb55da3 100644 (file)
@@ -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 @@ LCDTextDrawFilter::Mode cycle_lcdmode(LCDTextDrawFilter::Mode mode) {
 
 //////////////////////////////////////////////////////////////////////////////
 
+#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 @@ protected:
     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 @@ protected:
     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 @@ private:
     SkPath fClipPath;
 
     SkTouchGesture fGesture;
+    int      fZoomLevel;
+    SkScalar fZoomScale;
 
     enum CanvasType {
         kRaster_CanvasType,
@@ -269,6 +273,7 @@ private:
     int fScrollTestX, fScrollTestY;
 
     bool make3DReady();
+    void changeZoomLevel(int delta);
 
     void loadView(SkView*);
     void updateTitle();
@@ -340,6 +345,9 @@ SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
     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 @@ void SampleWindow::draw(SkCanvas* canvas) {
     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, &center);
+        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 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
                                                   bitmap.width(), bitmap.height(),
                                                   false, false);
                 fGpuCanvas->setDevice(device)->unref();
+                
+                fGpuCanvas->concat(canvas->getTotalMatrix());
                 canvas = fGpuCanvas;
 
             } else {
@@ -640,6 +667,21 @@ static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
     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 @@ bool SampleWindow::onHandleKey(SkKey key) {
             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 @@ bool SampleWindow::onHandleKey(SkKey key) {
 
 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 @@ void SampleWindow::updateTitle() {
     } else if (LCDTextDrawFilter::kForceOff_Mode == fLCDMode) {
         title.prepend("lcd ");
     }
+
+    if (fZoomLevel) {
+        title.prependf("{%d} ", fZoomLevel);
+    }
     this->setTitle(title.c_str());
 }
 
index d7e8dce..776d6da 100644 (file)
@@ -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 @@ protected:
         }
     }
 
+    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 @@ public:
         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 @@ protected:
     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 @@ protected:
     }
 
     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 @@ protected:
             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;
     }
index 7aefe14..14672e2 100644 (file)
@@ -370,8 +370,11 @@ bool SkWindow::onHandleKeyUp(SkKey key)
     return false;
 }
 
-bool SkWindow::handleClick(int x, int y, Click::State state)
-{
+bool SkWindow::handleClick(int x, int y, Click::State state) {
+    return this->onDispatchClick(x, y, state);
+}
+
+bool SkWindow::onDispatchClick(int x, int y, Click::State state) {
        bool handled = false;
 
        switch (state) {