1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #ifndef SkView_DEFINED 11 #define SkView_DEFINED 12 13 #include "SkEventSink.h" 14 #include "SkRect.h" 15 #include "SkDOM.h" 16 #include "SkTDict.h" 17 #include "SkMatrix.h" 18 19 class SkCanvas; 20 class SkLayerView; 21 22 /** \class SkView 23 24 SkView is the base class for screen management. All widgets and controls inherit 25 from SkView. 26 */ 27 class SkView : public SkEventSink { 28 public: 29 enum Flag_Shift { 30 kVisible_Shift, 31 kEnabled_Shift, 32 kFocusable_Shift, 33 kFlexH_Shift, 34 kFlexV_Shift, 35 kNoClip_Shift, 36 37 kFlagShiftCount 38 }; 39 enum Flag_Mask { 40 kVisible_Mask = 1 << kVisible_Shift, //!< set if the view is visible 41 kEnabled_Mask = 1 << kEnabled_Shift, //!< set if the view is enabled 42 kFocusable_Mask = 1 << kFocusable_Shift, //!< set if the view can receive focus 43 kFlexH_Mask = 1 << kFlexH_Shift, //!< set if the view's width is stretchable 44 kFlexV_Mask = 1 << kFlexV_Shift, //!< set if the view's height is stretchable 45 kNoClip_Mask = 1 << kNoClip_Shift, //!< set if the view is not clipped to its bounds 46 47 kAllFlagMasks = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount) 48 }; 49 50 SkView(uint32_t flags = 0); 51 virtual ~SkView(); 52 53 /** Return the flags associated with the view 54 */ getFlags()55 uint32_t getFlags() const { return fFlags; } 56 /** Set the flags associated with the view 57 */ 58 void setFlags(uint32_t flags); 59 60 /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags 61 */ isVisible()62 int isVisible() const { return fFlags & kVisible_Mask; } isEnabled()63 int isEnabled() const { return fFlags & kEnabled_Mask; } isFocusable()64 int isFocusable() const { return fFlags & kFocusable_Mask; } isClipToBounds()65 int isClipToBounds() const { return !(fFlags & kNoClip_Mask); } 66 /** Helper to set/clear the view's kVisible_Mask flag */ 67 void setVisibleP(bool); 68 void setEnabledP(bool); 69 void setFocusableP(bool); 70 void setClipToBounds(bool); 71 72 /** Return the view's width */ width()73 SkScalar width() const { return fWidth; } 74 /** Return the view's height */ height()75 SkScalar height() const { return fHeight; } 76 /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */ 77 void setSize(SkScalar width, SkScalar height); setSize(const SkPoint & size)78 void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); } setWidth(SkScalar width)79 void setWidth(SkScalar width) { this->setSize(width, fHeight); } setHeight(SkScalar height)80 void setHeight(SkScalar height) { this->setSize(fWidth, height); } 81 /** Return a rectangle set to [0, 0, width, height] */ 82 void getLocalBounds(SkRect* bounds) const; 83 84 /** Loc - the view's offset with respect to its parent in its view hiearchy. 85 NOTE: For more complex transforms, use Local Matrix. The tranformations 86 are applied in the following order: 87 canvas->translate(fLoc.fX, fLoc.fY); 88 canvas->concat(fMatrix); 89 */ 90 /** Return the view's left edge */ locX()91 SkScalar locX() const { return fLoc.fX; } 92 /** Return the view's top edge */ locY()93 SkScalar locY() const { return fLoc.fY; } 94 /** Set the view's left and top edge. This does not affect the view's size */ 95 void setLoc(SkScalar x, SkScalar y); setLoc(const SkPoint & loc)96 void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); } setLocX(SkScalar x)97 void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); } setLocY(SkScalar y)98 void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); } 99 100 /** Local Matrix - matrix used to tranform the view with respect to its 101 parent in its view hiearchy. Use setLocalMatrix to apply matrix 102 transformations to the current view and in turn affect its children. 103 NOTE: For simple offsets, use Loc. The transformations are applied in 104 the following order: 105 canvas->translate(fLoc.fX, fLoc.fY); 106 canvas->concat(fMatrix); 107 */ getLocalMatrix()108 const SkMatrix& getLocalMatrix() const { return fMatrix; } 109 void setLocalMatrix(const SkMatrix& matrix); 110 111 /** Offset (move) the view by the specified dx and dy. This does not affect the view's size */ 112 void offset(SkScalar dx, SkScalar dy); 113 114 /** Call this to have the view draw into the specified canvas. */ 115 virtual void draw(SkCanvas* canvas); 116 117 /** Call this to invalidate part of all of a view, requesting that the view's 118 draw method be called. The rectangle parameter specifies the part of the view 119 that should be redrawn. If it is null, it specifies the entire view bounds. 120 */ 121 void inval(SkRect* rectOrNull); 122 123 // Focus management 124 125 SkView* getFocusView() const; 126 bool hasFocus() const; 127 128 enum FocusDirection { 129 kNext_FocusDirection, 130 kPrev_FocusDirection, 131 132 kFocusDirectionCount 133 }; 134 bool acceptFocus(); 135 SkView* moveFocus(FocusDirection); 136 137 // Click handling 138 139 class Click { 140 public: 141 Click(SkView* target); 142 virtual ~Click(); 143 getType()144 const char* getType() const { return fType; } 145 bool isType(const char type[]) const; 146 void setType(const char type[]); // does NOT make a copy of the string 147 void copyType(const char type[]); // makes a copy of the string 148 149 enum State { 150 kDown_State, 151 kMoved_State, 152 kUp_State 153 }; 154 SkPoint fOrig, fPrev, fCurr; 155 SkIPoint fIOrig, fIPrev, fICurr; 156 State fState; 157 void* fOwner; 158 private: 159 SkEventSinkID fTargetID; 160 char* fType; 161 bool fWeOwnTheType; 162 163 void resetType(); 164 165 friend class SkView; 166 }; 167 Click* findClickHandler(SkScalar x, SkScalar y); 168 169 static void DoClickDown(Click*, int x, int y); 170 static void DoClickMoved(Click*, int x, int y); 171 static void DoClickUp(Click*, int x, int y); 172 173 /** Send the event to the view's parent, and its parent etc. until one of them 174 returns true from its onEvent call. This view is returned. If no parent handles 175 the event, null is returned. 176 */ 177 SkView* sendEventToParents(const SkEvent&); 178 /** Send the query to the view's parent, and its parent etc. until one of them 179 returns true from its onQuery call. This view is returned. If no parent handles 180 the query, null is returned. 181 */ 182 SkView* sendQueryToParents(SkEvent*); 183 184 // View hierarchy management 185 186 /** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */ getParent()187 SkView* getParent() const { return fParent; } 188 SkView* attachChildToFront(SkView* child); 189 /** Attach the child view to this view, and increment the child's reference count. The child view is added 190 such that it will be drawn before all other child views. 191 The child view parameter is returned. 192 */ 193 SkView* attachChildToBack(SkView* child); 194 /** If the view has a parent, detach the view from its parent and decrement the view's reference count. 195 If the parent was the only owner of the view, this will cause the view to be deleted. 196 */ 197 void detachFromParent(); 198 /** Attach the child view to this view, and increment the child's reference count. The child view is added 199 such that it will be drawn after all other child views. 200 The child view parameter is returned. 201 */ 202 /** Detach all child views from this view. */ 203 void detachAllChildren(); 204 205 /** Convert the specified point from global coordinates into view-local coordinates 206 */ globalToLocal(SkPoint * pt)207 void globalToLocal(SkPoint* pt) const { if (pt) this->globalToLocal(pt->fX, pt->fY, pt); } 208 /** Convert the specified x,y from global coordinates into view-local coordinates, returning 209 the answer in the local parameter. 210 */ 211 void globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const; 212 213 /** \class F2BIter 214 215 Iterator that will return each of this view's children, in 216 front-to-back order (the order used for clicking). The first 217 call to next() returns the front-most child view. When 218 next() returns null, there are no more child views. 219 */ 220 class F2BIter { 221 public: 222 F2BIter(const SkView* parent); 223 SkView* next(); 224 private: 225 SkView* fFirstChild, *fChild; 226 }; 227 228 /** \class B2FIter 229 230 Iterator that will return each of this view's children, in 231 back-to-front order (the order they are drawn). The first 232 call to next() returns the back-most child view. When 233 next() returns null, there are no more child views. 234 */ 235 class B2FIter { 236 public: 237 B2FIter(const SkView* parent); 238 SkView* next(); 239 private: 240 SkView* fFirstChild, *fChild; 241 }; 242 243 /** \class Artist 244 245 Install a subclass of this in a view (calling setArtist()), and then the 246 default implementation of that view's onDraw() will invoke this object 247 automatically. 248 */ 249 class Artist : public SkRefCnt { 250 public: 251 void draw(SkView*, SkCanvas*); 252 void inflate(const SkDOM&, const SkDOM::Node*); 253 protected: 254 virtual void onDraw(SkView*, SkCanvas*) = 0; 255 virtual void onInflate(const SkDOM&, const SkDOM::Node*); 256 }; 257 /** Return the artist attached to this view (or null). The artist's reference 258 count is not affected. 259 */ 260 Artist* getArtist() const; 261 /** Attach the specified artist (or null) to the view, replacing any existing 262 artist. If the new artist is not null, its reference count is incremented. 263 The artist parameter is returned. 264 */ 265 Artist* setArtist(Artist* artist); 266 267 /** \class Layout 268 269 Install a subclass of this in a view (calling setLayout()), and then the 270 default implementation of that view's onLayoutChildren() will invoke 271 this object automatically. 272 */ 273 class Layout : public SkRefCnt { 274 public: 275 void layoutChildren(SkView* parent); 276 void inflate(const SkDOM&, const SkDOM::Node*); 277 protected: 278 virtual void onLayoutChildren(SkView* parent) = 0; 279 virtual void onInflate(const SkDOM&, const SkDOM::Node*); 280 }; 281 282 /** Return the layout attached to this view (or null). The layout's reference 283 count is not affected. 284 */ 285 Layout* getLayout() const; 286 /** Attach the specified layout (or null) to the view, replacing any existing 287 layout. If the new layout is not null, its reference count is incremented. 288 The layout parameter is returned. 289 */ 290 Layout* setLayout(Layout*, bool invokeLayoutNow = true); 291 /** If a layout is attached to this view, call its layoutChildren() method 292 */ 293 void invokeLayout(); 294 295 /** Call this to initialize this view based on the specified XML node 296 */ 297 void inflate(const SkDOM& dom, const SkDOM::Node* node); 298 /** After a view hierarchy is inflated, this may be called with a dictionary 299 containing pairs of <name, view*>, where the name string was the view's 300 "id" attribute when it was inflated. 301 302 This will call the virtual onPostInflate for this view, and the recursively 303 call postInflate on all of the view's children. 304 */ 305 void postInflate(const SkTDict<SkView*>& ids); 306 307 SkDEBUGCODE(void dump(bool recurse) const;) 308 309 protected: 310 /** Override this to draw inside the view. Be sure to call the inherited version too */ 311 virtual void onDraw(SkCanvas*); 312 /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */ 313 virtual void onSizeChange(); 314 /** Override this if you want to handle an inval request from this view or one of its children. 315 Tyically this is only overridden by the by the "window". If your subclass does handle the 316 request, return true so the request will not continue to propogate to the parent. 317 */ 318 virtual bool handleInval(const SkRect*); 319 //! called once before all of the children are drawn (or clipped/translated) beforeChildren(SkCanvas * c)320 virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; } 321 //! called once after all of the children are drawn (or clipped/translated) afterChildren(SkCanvas * orig)322 virtual void afterChildren(SkCanvas* orig) {} 323 324 //! called right before this child's onDraw is called beforeChild(SkView * child,SkCanvas * canvas)325 virtual void beforeChild(SkView* child, SkCanvas* canvas) {} 326 //! called right after this child's onDraw is called afterChild(SkView * child,SkCanvas * canvas)327 virtual void afterChild(SkView* child, SkCanvas* canvas) {} 328 329 /** Override this if you might handle the click 330 */ 331 virtual Click* onFindClickHandler(SkScalar x, SkScalar y); 332 /** Override this to decide if your children are targets for a click. 333 The default returns true, in which case your children views will be 334 candidates for onFindClickHandler. Returning false wil skip the children 335 and just call your onFindClickHandler. 336 */ 337 virtual bool onSendClickToChildren(SkScalar x, SkScalar y); 338 /** Override this to track clicks, returning true as long as you want to track 339 the pen/mouse. 340 */ 341 virtual bool onClick(Click*); 342 /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */ 343 virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); 344 /** Override this if you want to perform post initialization work based on the ID dictionary built 345 during XML parsing. Be sure to call the inherited version too. 346 */ 347 virtual void onPostInflate(const SkTDict<SkView*>&); 348 349 public: 350 // default action is to inval the view 351 virtual void onFocusChange(bool gainFocusP); 352 protected: 353 354 // override these if you're acting as a layer/host onGetFocusView(SkView **)355 virtual bool onGetFocusView(SkView**) const { return false; } onSetFocusView(SkView *)356 virtual bool onSetFocusView(SkView*) { return false; } 357 358 private: 359 SkScalar fWidth, fHeight; 360 SkMatrix fMatrix; 361 SkPoint fLoc; 362 SkView* fParent; 363 SkView* fFirstChild; 364 SkView* fNextSibling; 365 SkView* fPrevSibling; 366 uint8_t fFlags; 367 uint8_t fContainsFocus; 368 369 friend class B2FIter; 370 friend class F2BIter; 371 372 friend class SkLayerView; 373 374 bool setFocusView(SkView* fvOrNull); 375 SkView* acceptFocus(FocusDirection); 376 void detachFromParent_NoLayout(); 377 /** Compute the matrix to transform view-local coordinates into global ones */ 378 void localToGlobal(SkMatrix* matrix) const; 379 }; 380 381 #endif 382 383