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