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