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