From: mike@reedtribe.org Date: Mon, 21 Mar 2011 00:53:39 +0000 (+0000) Subject: allow window-subclass to handle dispatching click events (for resize) X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~18813 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd0cd34067d103ace7c6739405cb7885d8ad3fb2;p=platform%2Fupstream%2FlibSkiaSharp.git 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/include/views/SkWindow.h b/include/views/SkWindow.h index ffba275..7b37779 100644 --- a/include/views/SkWindow.h +++ b/include/views/SkWindow.h @@ -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); 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 @@ 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, ¢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 @@ 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()); } 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 @@ 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; } diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp index 7aefe14..14672e2 100644 --- a/src/views/SkWindow.cpp +++ b/src/views/SkWindow.cpp @@ -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) {