1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/views/SkView.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,405 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#ifndef SkView_DEFINED 1.14 +#define SkView_DEFINED 1.15 + 1.16 +#include "SkEventSink.h" 1.17 +#include "SkRect.h" 1.18 +#include "SkDOM.h" 1.19 +#include "SkTDict.h" 1.20 +#include "SkMatrix.h" 1.21 +#include "SkMetaData.h" 1.22 + 1.23 +class SkCanvas; 1.24 +class SkLayerView; 1.25 + 1.26 +/** \class SkView 1.27 + 1.28 + SkView is the base class for screen management. All widgets and controls inherit 1.29 + from SkView. 1.30 +*/ 1.31 +class SkView : public SkEventSink { 1.32 +public: 1.33 + enum Flag_Shift { 1.34 + kVisible_Shift, 1.35 + kEnabled_Shift, 1.36 + kFocusable_Shift, 1.37 + kFlexH_Shift, 1.38 + kFlexV_Shift, 1.39 + kNoClip_Shift, 1.40 + 1.41 + kFlagShiftCount 1.42 + }; 1.43 + enum Flag_Mask { 1.44 + kVisible_Mask = 1 << kVisible_Shift, //!< set if the view is visible 1.45 + kEnabled_Mask = 1 << kEnabled_Shift, //!< set if the view is enabled 1.46 + kFocusable_Mask = 1 << kFocusable_Shift, //!< set if the view can receive focus 1.47 + kFlexH_Mask = 1 << kFlexH_Shift, //!< set if the view's width is stretchable 1.48 + kFlexV_Mask = 1 << kFlexV_Shift, //!< set if the view's height is stretchable 1.49 + kNoClip_Mask = 1 << kNoClip_Shift, //!< set if the view is not clipped to its bounds 1.50 + 1.51 + kAllFlagMasks = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount) 1.52 + }; 1.53 + 1.54 + SkView(uint32_t flags = 0); 1.55 + virtual ~SkView(); 1.56 + 1.57 + /** Return the flags associated with the view 1.58 + */ 1.59 + uint32_t getFlags() const { return fFlags; } 1.60 + /** Set the flags associated with the view 1.61 + */ 1.62 + void setFlags(uint32_t flags); 1.63 + 1.64 + /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags 1.65 + */ 1.66 + int isVisible() const { return fFlags & kVisible_Mask; } 1.67 + int isEnabled() const { return fFlags & kEnabled_Mask; } 1.68 + int isFocusable() const { return fFlags & kFocusable_Mask; } 1.69 + int isClipToBounds() const { return !(fFlags & kNoClip_Mask); } 1.70 + /** Helper to set/clear the view's kVisible_Mask flag */ 1.71 + void setVisibleP(bool); 1.72 + void setEnabledP(bool); 1.73 + void setFocusableP(bool); 1.74 + void setClipToBounds(bool); 1.75 + 1.76 + /** Return the view's width */ 1.77 + SkScalar width() const { return fWidth; } 1.78 + /** Return the view's height */ 1.79 + SkScalar height() const { return fHeight; } 1.80 + /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */ 1.81 + void setSize(SkScalar width, SkScalar height); 1.82 + void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); } 1.83 + void setWidth(SkScalar width) { this->setSize(width, fHeight); } 1.84 + void setHeight(SkScalar height) { this->setSize(fWidth, height); } 1.85 + /** Return a rectangle set to [0, 0, width, height] */ 1.86 + void getLocalBounds(SkRect* bounds) const; 1.87 + 1.88 + /** Loc - the view's offset with respect to its parent in its view hiearchy. 1.89 + NOTE: For more complex transforms, use Local Matrix. The tranformations 1.90 + are applied in the following order: 1.91 + canvas->translate(fLoc.fX, fLoc.fY); 1.92 + canvas->concat(fMatrix); 1.93 + */ 1.94 + /** Return the view's left edge */ 1.95 + SkScalar locX() const { return fLoc.fX; } 1.96 + /** Return the view's top edge */ 1.97 + SkScalar locY() const { return fLoc.fY; } 1.98 + /** Set the view's left and top edge. This does not affect the view's size */ 1.99 + void setLoc(SkScalar x, SkScalar y); 1.100 + void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); } 1.101 + void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); } 1.102 + void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); } 1.103 + 1.104 + /** Local Matrix - matrix used to tranform the view with respect to its 1.105 + parent in its view hiearchy. Use setLocalMatrix to apply matrix 1.106 + transformations to the current view and in turn affect its children. 1.107 + NOTE: For simple offsets, use Loc. The transformations are applied in 1.108 + the following order: 1.109 + canvas->translate(fLoc.fX, fLoc.fY); 1.110 + canvas->concat(fMatrix); 1.111 + */ 1.112 + const SkMatrix& getLocalMatrix() const { return fMatrix; } 1.113 + void setLocalMatrix(const SkMatrix& matrix); 1.114 + 1.115 + /** Offset (move) the view by the specified dx and dy. This does not affect the view's size */ 1.116 + void offset(SkScalar dx, SkScalar dy); 1.117 + 1.118 + /** Call this to have the view draw into the specified canvas. */ 1.119 + virtual void draw(SkCanvas* canvas); 1.120 + 1.121 + /** Call this to invalidate part of all of a view, requesting that the view's 1.122 + draw method be called. The rectangle parameter specifies the part of the view 1.123 + that should be redrawn. If it is null, it specifies the entire view bounds. 1.124 + */ 1.125 + void inval(SkRect* rectOrNull); 1.126 + 1.127 + // Focus management 1.128 + 1.129 + SkView* getFocusView() const; 1.130 + bool hasFocus() const; 1.131 + 1.132 + enum FocusDirection { 1.133 + kNext_FocusDirection, 1.134 + kPrev_FocusDirection, 1.135 + 1.136 + kFocusDirectionCount 1.137 + }; 1.138 + bool acceptFocus(); 1.139 + SkView* moveFocus(FocusDirection); 1.140 + 1.141 + // Click handling 1.142 + 1.143 + class Click { 1.144 + public: 1.145 + Click(SkView* target); 1.146 + virtual ~Click(); 1.147 + 1.148 + const char* getType() const { return fType; } 1.149 + bool isType(const char type[]) const; 1.150 + void setType(const char type[]); // does NOT make a copy of the string 1.151 + void copyType(const char type[]); // makes a copy of the string 1.152 + 1.153 + enum State { 1.154 + kDown_State, 1.155 + kMoved_State, 1.156 + kUp_State 1.157 + }; 1.158 + SkPoint fOrig, fPrev, fCurr; 1.159 + SkIPoint fIOrig, fIPrev, fICurr; 1.160 + State fState; 1.161 + void* fOwner; 1.162 + unsigned fModifierKeys; 1.163 + 1.164 + SkMetaData fMeta; 1.165 + private: 1.166 + SkEventSinkID fTargetID; 1.167 + char* fType; 1.168 + bool fWeOwnTheType; 1.169 + 1.170 + void resetType(); 1.171 + 1.172 + friend class SkView; 1.173 + }; 1.174 + Click* findClickHandler(SkScalar x, SkScalar y, unsigned modifierKeys); 1.175 + 1.176 + static void DoClickDown(Click*, int x, int y, unsigned modi); 1.177 + static void DoClickMoved(Click*, int x, int y, unsigned modi); 1.178 + static void DoClickUp(Click*, int x, int y, unsigned modi); 1.179 + 1.180 + /** Send the event to the view's parent, and its parent etc. until one of them 1.181 + returns true from its onEvent call. This view is returned. If no parent handles 1.182 + the event, null is returned. 1.183 + */ 1.184 + SkView* sendEventToParents(const SkEvent&); 1.185 + /** Send the query to the view's parent, and its parent etc. until one of them 1.186 + returns true from its onQuery call. This view is returned. If no parent handles 1.187 + the query, null is returned. 1.188 + */ 1.189 + SkView* sendQueryToParents(SkEvent*); 1.190 + 1.191 + // View hierarchy management 1.192 + 1.193 + /** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */ 1.194 + SkView* getParent() const { return fParent; } 1.195 + SkView* attachChildToFront(SkView* child); 1.196 + /** Attach the child view to this view, and increment the child's reference count. The child view is added 1.197 + such that it will be drawn before all other child views. 1.198 + The child view parameter is returned. 1.199 + */ 1.200 + SkView* attachChildToBack(SkView* child); 1.201 + /** If the view has a parent, detach the view from its parent and decrement the view's reference count. 1.202 + If the parent was the only owner of the view, this will cause the view to be deleted. 1.203 + */ 1.204 + void detachFromParent(); 1.205 + /** Attach the child view to this view, and increment the child's reference count. The child view is added 1.206 + such that it will be drawn after all other child views. 1.207 + The child view parameter is returned. 1.208 + */ 1.209 + /** Detach all child views from this view. */ 1.210 + void detachAllChildren(); 1.211 + 1.212 + /** Convert the specified point from global coordinates into view-local coordinates 1.213 + * Return true on success; false on failure 1.214 + */ 1.215 + bool globalToLocal(SkPoint* pt) const { 1.216 + if (NULL != pt) { 1.217 + return this->globalToLocal(pt->fX, pt->fY, pt); 1.218 + } 1.219 + return true; // nothing to do so return true 1.220 + } 1.221 + /** Convert the specified x,y from global coordinates into view-local coordinates, returning 1.222 + the answer in the local parameter. 1.223 + */ 1.224 + bool globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const; 1.225 + 1.226 + /** \class F2BIter 1.227 + 1.228 + Iterator that will return each of this view's children, in 1.229 + front-to-back order (the order used for clicking). The first 1.230 + call to next() returns the front-most child view. When 1.231 + next() returns null, there are no more child views. 1.232 + */ 1.233 + class F2BIter { 1.234 + public: 1.235 + F2BIter(const SkView* parent); 1.236 + SkView* next(); 1.237 + private: 1.238 + SkView* fFirstChild, *fChild; 1.239 + }; 1.240 + 1.241 + /** \class B2FIter 1.242 + 1.243 + Iterator that will return each of this view's children, in 1.244 + back-to-front order (the order they are drawn). The first 1.245 + call to next() returns the back-most child view. When 1.246 + next() returns null, there are no more child views. 1.247 + */ 1.248 + class B2FIter { 1.249 + public: 1.250 + B2FIter(const SkView* parent); 1.251 + SkView* next(); 1.252 + private: 1.253 + SkView* fFirstChild, *fChild; 1.254 + }; 1.255 + 1.256 + /** \class Artist 1.257 + 1.258 + Install a subclass of this in a view (calling setArtist()), and then the 1.259 + default implementation of that view's onDraw() will invoke this object 1.260 + automatically. 1.261 + */ 1.262 + class Artist : public SkRefCnt { 1.263 + public: 1.264 + SK_DECLARE_INST_COUNT(Artist) 1.265 + 1.266 + void draw(SkView*, SkCanvas*); 1.267 + void inflate(const SkDOM&, const SkDOM::Node*); 1.268 + protected: 1.269 + virtual void onDraw(SkView*, SkCanvas*) = 0; 1.270 + virtual void onInflate(const SkDOM&, const SkDOM::Node*); 1.271 + private: 1.272 + typedef SkRefCnt INHERITED; 1.273 + }; 1.274 + /** Return the artist attached to this view (or null). The artist's reference 1.275 + count is not affected. 1.276 + */ 1.277 + Artist* getArtist() const; 1.278 + /** Attach the specified artist (or null) to the view, replacing any existing 1.279 + artist. If the new artist is not null, its reference count is incremented. 1.280 + The artist parameter is returned. 1.281 + */ 1.282 + Artist* setArtist(Artist* artist); 1.283 + 1.284 + /** \class Layout 1.285 + 1.286 + Install a subclass of this in a view (calling setLayout()), and then the 1.287 + default implementation of that view's onLayoutChildren() will invoke 1.288 + this object automatically. 1.289 + */ 1.290 + class Layout : public SkRefCnt { 1.291 + public: 1.292 + SK_DECLARE_INST_COUNT(Layout) 1.293 + 1.294 + void layoutChildren(SkView* parent); 1.295 + void inflate(const SkDOM&, const SkDOM::Node*); 1.296 + protected: 1.297 + virtual void onLayoutChildren(SkView* parent) = 0; 1.298 + virtual void onInflate(const SkDOM&, const SkDOM::Node*); 1.299 + private: 1.300 + typedef SkRefCnt INHERITED; 1.301 + }; 1.302 + 1.303 + /** Return the layout attached to this view (or null). The layout's reference 1.304 + count is not affected. 1.305 + */ 1.306 + Layout* getLayout() const; 1.307 + /** Attach the specified layout (or null) to the view, replacing any existing 1.308 + layout. If the new layout is not null, its reference count is incremented. 1.309 + The layout parameter is returned. 1.310 + */ 1.311 + Layout* setLayout(Layout*, bool invokeLayoutNow = true); 1.312 + /** If a layout is attached to this view, call its layoutChildren() method 1.313 + */ 1.314 + void invokeLayout(); 1.315 + 1.316 + /** Call this to initialize this view based on the specified XML node 1.317 + */ 1.318 + void inflate(const SkDOM& dom, const SkDOM::Node* node); 1.319 + /** After a view hierarchy is inflated, this may be called with a dictionary 1.320 + containing pairs of <name, view*>, where the name string was the view's 1.321 + "id" attribute when it was inflated. 1.322 + 1.323 + This will call the virtual onPostInflate for this view, and the recursively 1.324 + call postInflate on all of the view's children. 1.325 + */ 1.326 + void postInflate(const SkTDict<SkView*>& ids); 1.327 + 1.328 + SkDEBUGCODE(void dump(bool recurse) const;) 1.329 + 1.330 +protected: 1.331 + /** Override this to draw inside the view. Be sure to call the inherited version too */ 1.332 + virtual void onDraw(SkCanvas*); 1.333 + /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */ 1.334 + virtual void onSizeChange(); 1.335 + /** Override this if you want to handle an inval request from this view or one of its children. 1.336 + Tyically this is only overridden by the by the "window". If your subclass does handle the 1.337 + request, return true so the request will not continue to propogate to the parent. 1.338 + */ 1.339 + virtual bool handleInval(const SkRect*); 1.340 + //! called once before all of the children are drawn (or clipped/translated) 1.341 + virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; } 1.342 + //! called once after all of the children are drawn (or clipped/translated) 1.343 + virtual void afterChildren(SkCanvas* orig) {} 1.344 + 1.345 + //! called right before this child's onDraw is called 1.346 + virtual void beforeChild(SkView* child, SkCanvas* canvas) {} 1.347 + //! called right after this child's onDraw is called 1.348 + virtual void afterChild(SkView* child, SkCanvas* canvas) {} 1.349 + 1.350 + /** Override this if you might handle the click 1.351 + */ 1.352 + virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi); 1.353 + /** Override this to decide if your children are targets for a click. 1.354 + The default returns true, in which case your children views will be 1.355 + candidates for onFindClickHandler. Returning false wil skip the children 1.356 + and just call your onFindClickHandler. 1.357 + */ 1.358 + virtual bool onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi); 1.359 + /** Override this to track clicks, returning true as long as you want to track 1.360 + the pen/mouse. 1.361 + */ 1.362 + virtual bool onClick(Click*); 1.363 + /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */ 1.364 + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); 1.365 + /** Override this if you want to perform post initialization work based on the ID dictionary built 1.366 + during XML parsing. Be sure to call the inherited version too. 1.367 + */ 1.368 + virtual void onPostInflate(const SkTDict<SkView*>&); 1.369 + 1.370 +public: 1.371 +#ifdef SK_DEBUG 1.372 + void validate() const; 1.373 +#else 1.374 + void validate() const {} 1.375 +#endif 1.376 + // default action is to inval the view 1.377 + virtual void onFocusChange(bool gainFocusP); 1.378 + 1.379 +protected: 1.380 + 1.381 + // override these if you're acting as a layer/host 1.382 + virtual bool onGetFocusView(SkView**) const { return false; } 1.383 + virtual bool onSetFocusView(SkView*) { return false; } 1.384 + 1.385 +private: 1.386 + SkScalar fWidth, fHeight; 1.387 + SkMatrix fMatrix; 1.388 + SkPoint fLoc; 1.389 + SkView* fParent; 1.390 + SkView* fFirstChild; 1.391 + SkView* fNextSibling; 1.392 + SkView* fPrevSibling; 1.393 + uint8_t fFlags; 1.394 + uint8_t fContainsFocus; 1.395 + 1.396 + friend class B2FIter; 1.397 + friend class F2BIter; 1.398 + 1.399 + friend class SkLayerView; 1.400 + 1.401 + bool setFocusView(SkView* fvOrNull); 1.402 + SkView* acceptFocus(FocusDirection); 1.403 + void detachFromParent_NoLayout(); 1.404 + /** Compute the matrix to transform view-local coordinates into global ones */ 1.405 + void localToGlobal(SkMatrix* matrix) const; 1.406 +}; 1.407 + 1.408 +#endif