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         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 
    300 protected:
    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 
    340 public:
    341     // default action is to inval the view
    342     virtual void    onFocusChange(bool gainFocusP);
    343 protected:
    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 
    349 private:
    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