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