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