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
25class SkCanvas;
26class SkLayerView;
27
28/** \class SkView
29
30    SkView is the base class for screen management. All widgets and controls inherit
31    from SkView.
32*/
33class SkView : public SkEventSink {
34public:
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
300protected:
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
340public:
341    // default action is to inval the view
342    virtual void    onFocusChange(bool gainFocusP);
343protected:
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
349private:
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