Home | History | Annotate | Download | only in views
      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     */
     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     */
     66     int         isVisible() const { return fFlags & kVisible_Mask; }
     67     int         isEnabled() const { return fFlags & kEnabled_Mask; }
     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 */
     75     SkScalar    width() const { return fWidth; }
     76     /** Return the view's 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);
     80     void        setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }
     81     void        setWidth(SkScalar width) { this->setSize(width, fHeight); }
     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 */
     87     SkScalar    locX() const { return fLoc.fX; }
     88     /** Return the view's top edge */
     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);
     92     void        setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); }
     93     void        setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); }
     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 
    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     */
    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. */
    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     */
    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)
    307     virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; }
    308     //! called once after all of the children are drawn (or clipped/translated)
    309     virtual void afterChildren(SkCanvas* orig) {}
    310 
    311     //! called right before this child's onDraw is called
    312     virtual void beforeChild(SkView* child, SkCanvas* canvas) {}
    313     //! called right after this child's onDraw is called
    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
    342     virtual bool    onGetFocusView(SkView**) const { return false; }
    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