• 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     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