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