SkView.h revision 80bacfeb4bda06541e8695bd502229727bccfeab
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 19class SkCanvas; 20class SkLayerView; 21 22/** \class SkView 23 24 SkView is the base class for screen management. All widgets and controls inherit 25 from SkView. 26*/ 27class SkView : public SkEventSink { 28public: 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 */ 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 */ 62 int isVisible() const { return fFlags & kVisible_Mask; } 63 int isEnabled() const { return fFlags & kEnabled_Mask; } 64 int isFocusable() const { return fFlags & kFocusable_Mask; } 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 */ 73 SkScalar width() const { return fWidth; } 74 /** Return the view's 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); 78 void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); } 79 void setWidth(SkScalar width) { this->setSize(width, fHeight); } 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 */ 91 SkScalar locX() const { return fLoc.fX; } 92 /** Return the view's top edge */ 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); 96 void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); } 97 void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); } 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 */ 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 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. */ 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 * Return true on success; false on failure 207 */ 208 bool globalToLocal(SkPoint* pt) const { 209 if (NULL != pt) { 210 return this->globalToLocal(pt->fX, pt->fY, pt); 211 } 212 return true; // nothing to do so return true 213 } 214 /** Convert the specified x,y from global coordinates into view-local coordinates, returning 215 the answer in the local parameter. 216 */ 217 bool globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const; 218 219 /** \class F2BIter 220 221 Iterator that will return each of this view's children, in 222 front-to-back order (the order used for clicking). The first 223 call to next() returns the front-most child view. When 224 next() returns null, there are no more child views. 225 */ 226 class F2BIter { 227 public: 228 F2BIter(const SkView* parent); 229 SkView* next(); 230 private: 231 SkView* fFirstChild, *fChild; 232 }; 233 234 /** \class B2FIter 235 236 Iterator that will return each of this view's children, in 237 back-to-front order (the order they are drawn). The first 238 call to next() returns the back-most child view. When 239 next() returns null, there are no more child views. 240 */ 241 class B2FIter { 242 public: 243 B2FIter(const SkView* parent); 244 SkView* next(); 245 private: 246 SkView* fFirstChild, *fChild; 247 }; 248 249 /** \class Artist 250 251 Install a subclass of this in a view (calling setArtist()), and then the 252 default implementation of that view's onDraw() will invoke this object 253 automatically. 254 */ 255 class Artist : public SkRefCnt { 256 public: 257 SK_DECLARE_INST_COUNT(Artist) 258 259 void draw(SkView*, SkCanvas*); 260 void inflate(const SkDOM&, const SkDOM::Node*); 261 protected: 262 virtual void onDraw(SkView*, SkCanvas*) = 0; 263 virtual void onInflate(const SkDOM&, const SkDOM::Node*); 264 private: 265 typedef SkRefCnt INHERITED; 266 }; 267 /** Return the artist attached to this view (or null). The artist's reference 268 count is not affected. 269 */ 270 Artist* getArtist() const; 271 /** Attach the specified artist (or null) to the view, replacing any existing 272 artist. If the new artist is not null, its reference count is incremented. 273 The artist parameter is returned. 274 */ 275 Artist* setArtist(Artist* artist); 276 277 /** \class Layout 278 279 Install a subclass of this in a view (calling setLayout()), and then the 280 default implementation of that view's onLayoutChildren() will invoke 281 this object automatically. 282 */ 283 class Layout : public SkRefCnt { 284 public: 285 SK_DECLARE_INST_COUNT(Layout) 286 287 void layoutChildren(SkView* parent); 288 void inflate(const SkDOM&, const SkDOM::Node*); 289 protected: 290 virtual void onLayoutChildren(SkView* parent) = 0; 291 virtual void onInflate(const SkDOM&, const SkDOM::Node*); 292 private: 293 typedef SkRefCnt INHERITED; 294 }; 295 296 /** Return the layout attached to this view (or null). The layout's reference 297 count is not affected. 298 */ 299 Layout* getLayout() const; 300 /** Attach the specified layout (or null) to the view, replacing any existing 301 layout. If the new layout is not null, its reference count is incremented. 302 The layout parameter is returned. 303 */ 304 Layout* setLayout(Layout*, bool invokeLayoutNow = true); 305 /** If a layout is attached to this view, call its layoutChildren() method 306 */ 307 void invokeLayout(); 308 309 /** Call this to initialize this view based on the specified XML node 310 */ 311 void inflate(const SkDOM& dom, const SkDOM::Node* node); 312 /** After a view hierarchy is inflated, this may be called with a dictionary 313 containing pairs of <name, view*>, where the name string was the view's 314 "id" attribute when it was inflated. 315 316 This will call the virtual onPostInflate for this view, and the recursively 317 call postInflate on all of the view's children. 318 */ 319 void postInflate(const SkTDict<SkView*>& ids); 320 321 SkDEBUGCODE(void dump(bool recurse) const;) 322 323protected: 324 /** Override this to draw inside the view. Be sure to call the inherited version too */ 325 virtual void onDraw(SkCanvas*); 326 /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */ 327 virtual void onSizeChange(); 328 /** Override this if you want to handle an inval request from this view or one of its children. 329 Tyically this is only overridden by the by the "window". If your subclass does handle the 330 request, return true so the request will not continue to propogate to the parent. 331 */ 332 virtual bool handleInval(const SkRect*); 333 //! called once before all of the children are drawn (or clipped/translated) 334 virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; } 335 //! called once after all of the children are drawn (or clipped/translated) 336 virtual void afterChildren(SkCanvas* orig) {} 337 338 //! called right before this child's onDraw is called 339 virtual void beforeChild(SkView* child, SkCanvas* canvas) {} 340 //! called right after this child's onDraw is called 341 virtual void afterChild(SkView* child, SkCanvas* canvas) {} 342 343 /** Override this if you might handle the click 344 */ 345 virtual Click* onFindClickHandler(SkScalar x, SkScalar y); 346 /** Override this to decide if your children are targets for a click. 347 The default returns true, in which case your children views will be 348 candidates for onFindClickHandler. Returning false wil skip the children 349 and just call your onFindClickHandler. 350 */ 351 virtual bool onSendClickToChildren(SkScalar x, SkScalar y); 352 /** Override this to track clicks, returning true as long as you want to track 353 the pen/mouse. 354 */ 355 virtual bool onClick(Click*); 356 /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */ 357 virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); 358 /** Override this if you want to perform post initialization work based on the ID dictionary built 359 during XML parsing. Be sure to call the inherited version too. 360 */ 361 virtual void onPostInflate(const SkTDict<SkView*>&); 362 363public: 364 // default action is to inval the view 365 virtual void onFocusChange(bool gainFocusP); 366protected: 367 368 // override these if you're acting as a layer/host 369 virtual bool onGetFocusView(SkView**) const { return false; } 370 virtual bool onSetFocusView(SkView*) { return false; } 371 372private: 373 SkScalar fWidth, fHeight; 374 SkMatrix fMatrix; 375 SkPoint fLoc; 376 SkView* fParent; 377 SkView* fFirstChild; 378 SkView* fNextSibling; 379 SkView* fPrevSibling; 380 uint8_t fFlags; 381 uint8_t fContainsFocus; 382 383 friend class B2FIter; 384 friend class F2BIter; 385 386 friend class SkLayerView; 387 388 bool setFocusView(SkView* fvOrNull); 389 SkView* acceptFocus(FocusDirection); 390 void detachFromParent_NoLayout(); 391 /** Compute the matrix to transform view-local coordinates into global ones */ 392 void localToGlobal(SkMatrix* matrix) const; 393}; 394 395#endif 396 397