Home | History | Annotate | Download | only in views
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      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 #include "SkView.h"
      9 #include "SkCanvas.h"
     10 
     11 ////////////////////////////////////////////////////////////////////////
     12 
     13 SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags))
     14 {
     15     fWidth = fHeight = 0;
     16     fLoc.set(0, 0);
     17     fParent = fFirstChild = fNextSibling = fPrevSibling = NULL;
     18     fMatrix.setIdentity();
     19     fContainsFocus = 0;
     20 }
     21 
     22 SkView::~SkView()
     23 {
     24     this->detachAllChildren();
     25 }
     26 
     27 void SkView::setFlags(uint32_t flags)
     28 {
     29     SkASSERT((flags & ~kAllFlagMasks) == 0);
     30 
     31     uint32_t diff = fFlags ^ flags;
     32 
     33     if (diff & kVisible_Mask)
     34         this->inval(NULL);
     35 
     36     fFlags = SkToU8(flags);
     37 
     38     if (diff & kVisible_Mask)
     39     {
     40         this->inval(NULL);
     41     }
     42 }
     43 
     44 void SkView::setVisibleP(bool pred)
     45 {
     46     this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift));
     47 }
     48 
     49 void SkView::setEnabledP(bool pred)
     50 {
     51     this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift));
     52 }
     53 
     54 void SkView::setFocusableP(bool pred)
     55 {
     56     this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
     57 }
     58 
     59 void SkView::setClipToBounds(bool pred) {
     60     this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
     61 }
     62 
     63 void SkView::setSize(SkScalar width, SkScalar height)
     64 {
     65     width = SkMaxScalar(0, width);
     66     height = SkMaxScalar(0, height);
     67 
     68     if (fWidth != width || fHeight != height)
     69     {
     70         this->inval(NULL);
     71         fWidth = width;
     72         fHeight = height;
     73         this->inval(NULL);
     74         this->onSizeChange();
     75         this->invokeLayout();
     76     }
     77 }
     78 
     79 void SkView::setLoc(SkScalar x, SkScalar y)
     80 {
     81     if (fLoc.fX != x || fLoc.fY != y)
     82     {
     83         this->inval(NULL);
     84         fLoc.set(x, y);
     85         this->inval(NULL);
     86     }
     87 }
     88 
     89 void SkView::offset(SkScalar dx, SkScalar dy)
     90 {
     91     if (dx || dy)
     92         this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
     93 }
     94 
     95 void SkView::setLocalMatrix(const SkMatrix& matrix)
     96 {
     97     this->inval(NULL);
     98     fMatrix = matrix;
     99     this->inval(NULL);
    100 }
    101 
    102 void SkView::draw(SkCanvas* canvas)
    103 {
    104     if (fWidth && fHeight && this->isVisible())
    105     {
    106         SkRect    r;
    107         r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight);
    108         if (this->isClipToBounds() &&
    109             canvas->quickReject(r)) {
    110                 return;
    111         }
    112 
    113         SkAutoCanvasRestore    as(canvas, true);
    114 
    115         if (this->isClipToBounds()) {
    116             canvas->clipRect(r);
    117         }
    118 
    119         canvas->translate(fLoc.fX, fLoc.fY);
    120         canvas->concat(fMatrix);
    121 
    122         if (fParent) {
    123             fParent->beforeChild(this, canvas);
    124         }
    125 
    126         int sc = canvas->save();
    127         this->onDraw(canvas);
    128         canvas->restoreToCount(sc);
    129 
    130         if (fParent) {
    131             fParent->afterChild(this, canvas);
    132         }
    133 
    134         B2FIter    iter(this);
    135         SkView*    child;
    136 
    137         SkCanvas* childCanvas = this->beforeChildren(canvas);
    138 
    139         while ((child = iter.next()) != NULL)
    140             child->draw(childCanvas);
    141 
    142         this->afterChildren(canvas);
    143     }
    144 }
    145 
    146 void SkView::inval(SkRect* rect) {
    147     SkView*    view = this;
    148     SkRect storage;
    149 
    150     for (;;) {
    151         if (!view->isVisible()) {
    152             return;
    153         }
    154         if (view->isClipToBounds()) {
    155             SkRect bounds;
    156             view->getLocalBounds(&bounds);
    157             if (rect && !bounds.intersect(*rect)) {
    158                 return;
    159             }
    160             storage = bounds;
    161             rect = &storage;
    162         }
    163         if (view->handleInval(rect)) {
    164             return;
    165         }
    166 
    167         SkView* parent = view->fParent;
    168         if (parent == NULL) {
    169             return;
    170         }
    171 
    172         if (rect) {
    173             rect->offset(view->fLoc.fX, view->fLoc.fY);
    174         }
    175         view = parent;
    176     }
    177 }
    178 
    179 ////////////////////////////////////////////////////////////////////////////
    180 
    181 bool SkView::setFocusView(SkView* fv)
    182 {
    183     SkView* view = this;
    184 
    185     do {
    186         if (view->onSetFocusView(fv))
    187             return true;
    188     } while ((view = view->fParent) != NULL);
    189     return false;
    190 }
    191 
    192 SkView* SkView::getFocusView() const
    193 {
    194     SkView*            focus = NULL;
    195     const SkView*    view = this;
    196     do {
    197         if (view->onGetFocusView(&focus))
    198             break;
    199     } while ((view = view->fParent) != NULL);
    200     return focus;
    201 }
    202 
    203 bool SkView::hasFocus() const
    204 {
    205     return this == this->getFocusView();
    206 }
    207 
    208 bool SkView::acceptFocus()
    209 {
    210     return this->isFocusable() && this->setFocusView(this);
    211 }
    212 
    213 /*
    214     Try to give focus to this view, or its children
    215 */
    216 SkView* SkView::acceptFocus(FocusDirection dir)
    217 {
    218     if (dir == kNext_FocusDirection)
    219     {
    220         if (this->acceptFocus())
    221             return this;
    222 
    223         B2FIter    iter(this);
    224         SkView*    child, *focus;
    225         while ((child = iter.next()) != NULL)
    226             if ((focus = child->acceptFocus(dir)) != NULL)
    227                 return focus;
    228     }
    229     else // prev
    230     {
    231         F2BIter    iter(this);
    232         SkView*    child, *focus;
    233         while ((child = iter.next()) != NULL)
    234             if ((focus = child->acceptFocus(dir)) != NULL)
    235                 return focus;
    236 
    237         if (this->acceptFocus())
    238             return this;
    239     }
    240 
    241     return NULL;
    242 }
    243 
    244 SkView* SkView::moveFocus(FocusDirection dir)
    245 {
    246     SkView* focus = this->getFocusView();
    247 
    248     if (focus == NULL)
    249     {    // start with the root
    250         focus = this;
    251         while (focus->fParent)
    252             focus = focus->fParent;
    253     }
    254 
    255     SkView*    child, *parent;
    256 
    257     if (dir == kNext_FocusDirection)
    258     {
    259         parent = focus;
    260         child = focus->fFirstChild;
    261         if (child)
    262             goto FIRST_CHILD;
    263         else
    264             goto NEXT_SIB;
    265 
    266         do {
    267             while (child != parent->fFirstChild)
    268             {
    269     FIRST_CHILD:
    270                 if ((focus = child->acceptFocus(dir)) != NULL)
    271                     return focus;
    272                 child = child->fNextSibling;
    273             }
    274     NEXT_SIB:
    275             child = parent->fNextSibling;
    276             parent = parent->fParent;
    277         } while (parent != NULL);
    278     }
    279     else    // prevfocus
    280     {
    281         parent = focus->fParent;
    282         if (parent == NULL)    // we're the root
    283             return focus->acceptFocus(dir);
    284         else
    285         {
    286             child = focus;
    287             while (parent)
    288             {
    289                 while (child != parent->fFirstChild)
    290                 {
    291                     child = child->fPrevSibling;
    292                     if ((focus = child->acceptFocus(dir)) != NULL)
    293                         return focus;
    294                 }
    295                 if (parent->acceptFocus())
    296                     return parent;
    297 
    298                 child = parent;
    299                 parent = parent->fParent;
    300             }
    301         }
    302     }
    303     return NULL;
    304 }
    305 
    306 void SkView::onFocusChange(bool gainFocusP)
    307 {
    308     this->inval(NULL);
    309 }
    310 
    311 ////////////////////////////////////////////////////////////////////////////
    312 
    313 SkView::Click::Click(SkView* target)
    314 {
    315     SkASSERT(target);
    316     fTargetID = target->getSinkID();
    317     fType = NULL;
    318     fWeOwnTheType = false;
    319     fOwner = NULL;
    320 }
    321 
    322 SkView::Click::~Click()
    323 {
    324     this->resetType();
    325 }
    326 
    327 void SkView::Click::resetType()
    328 {
    329     if (fWeOwnTheType)
    330     {
    331         sk_free(fType);
    332         fWeOwnTheType = false;
    333     }
    334     fType = NULL;
    335 }
    336 
    337 bool SkView::Click::isType(const char type[]) const
    338 {
    339     const char* t = fType;
    340 
    341     if (type == t)
    342         return true;
    343 
    344     if (type == NULL)
    345         type = "";
    346     if (t == NULL)
    347         t = "";
    348     return !strcmp(t, type);
    349 }
    350 
    351 void SkView::Click::setType(const char type[])
    352 {
    353     this->resetType();
    354     fType = (char*)type;
    355 }
    356 
    357 void SkView::Click::copyType(const char type[])
    358 {
    359     if (fType != type)
    360     {
    361         this->resetType();
    362         if (type)
    363         {
    364             size_t    len = strlen(type) + 1;
    365             fType = (char*)sk_malloc_throw(len);
    366             memcpy(fType, type, len);
    367             fWeOwnTheType = true;
    368         }
    369     }
    370 }
    371 
    372 SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) {
    373     if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
    374         return NULL;
    375     }
    376 
    377     if (this->onSendClickToChildren(x, y, modi)) {
    378         F2BIter    iter(this);
    379         SkView*    child;
    380 
    381         while ((child = iter.next()) != NULL)
    382         {
    383             SkPoint p;
    384             if (!child->globalToLocal(x, y, &p)) {
    385                 continue;
    386             }
    387 
    388             Click* click = child->findClickHandler(p.fX, p.fY, modi);
    389 
    390             if (click) {
    391                 return click;
    392             }
    393         }
    394     }
    395 
    396     return this->onFindClickHandler(x, y, modi);
    397 }
    398 
    399 void SkView::DoClickDown(Click* click, int x, int y, unsigned modi)
    400 {
    401     SkASSERT(click);
    402 
    403     SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
    404     if (NULL == target) {
    405         return;
    406     }
    407 
    408     click->fIOrig.set(x, y);
    409     click->fICurr = click->fIPrev = click->fIOrig;
    410 
    411     click->fOrig.iset(x, y);
    412     if (!target->globalToLocal(&click->fOrig)) {
    413         // no history to let us recover from this failure
    414         return;
    415     }
    416     click->fPrev = click->fCurr = click->fOrig;
    417 
    418     click->fState = Click::kDown_State;
    419     click->fModifierKeys = modi;
    420     target->onClick(click);
    421 }
    422 
    423 void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi)
    424 {
    425     SkASSERT(click);
    426 
    427     SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
    428     if (NULL == target) {
    429         return;
    430     }
    431 
    432     click->fIPrev = click->fICurr;
    433     click->fICurr.set(x, y);
    434 
    435     click->fPrev = click->fCurr;
    436     click->fCurr.iset(x, y);
    437     if (!target->globalToLocal(&click->fCurr)) {
    438         // on failure pretend the mouse didn't move
    439         click->fCurr = click->fPrev;
    440     }
    441 
    442     click->fState = Click::kMoved_State;
    443     click->fModifierKeys = modi;
    444     target->onClick(click);
    445 }
    446 
    447 void SkView::DoClickUp(Click* click, int x, int y, unsigned modi)
    448 {
    449     SkASSERT(click);
    450 
    451     SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
    452     if (NULL == target) {
    453         return;
    454     }
    455 
    456     click->fIPrev = click->fICurr;
    457     click->fICurr.set(x, y);
    458 
    459     click->fPrev = click->fCurr;
    460     click->fCurr.iset(x, y);
    461     if (!target->globalToLocal(&click->fCurr)) {
    462         // on failure pretend the mouse didn't move
    463         click->fCurr = click->fPrev;
    464     }
    465 
    466     click->fState = Click::kUp_State;
    467     click->fModifierKeys = modi;
    468     target->onClick(click);
    469 }
    470 
    471 //////////////////////////////////////////////////////////////////////
    472 
    473 void SkView::invokeLayout() {
    474     SkView::Layout* layout = this->getLayout();
    475 
    476     if (layout) {
    477         layout->layoutChildren(this);
    478     }
    479 }
    480 
    481 void SkView::onDraw(SkCanvas* canvas) {
    482     Artist* artist = this->getArtist();
    483 
    484     if (artist) {
    485         artist->draw(this, canvas);
    486     }
    487 }
    488 
    489 void SkView::onSizeChange() {}
    490 
    491 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) {
    492     return true;
    493 }
    494 
    495 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
    496     return NULL;
    497 }
    498 
    499 bool SkView::onClick(Click*) {
    500     return false;
    501 }
    502 
    503 bool SkView::handleInval(const SkRect*) {
    504     return false;
    505 }
    506 
    507 //////////////////////////////////////////////////////////////////////
    508 
    509 void SkView::getLocalBounds(SkRect* bounds) const {
    510     if (bounds) {
    511         bounds->set(0, 0, fWidth, fHeight);
    512     }
    513 }
    514 
    515 //////////////////////////////////////////////////////////////////////
    516 //////////////////////////////////////////////////////////////////////
    517 
    518 void SkView::detachFromParent_NoLayout() {
    519     this->validate();
    520     if (fParent == NULL) {
    521         return;
    522     }
    523 
    524     if (fContainsFocus) {
    525         (void)this->setFocusView(NULL);
    526     }
    527 
    528     this->inval(NULL);
    529 
    530     SkView* next = NULL;
    531 
    532     if (fNextSibling != this) {   // do we have any siblings
    533         fNextSibling->fPrevSibling = fPrevSibling;
    534         fPrevSibling->fNextSibling = fNextSibling;
    535         next = fNextSibling;
    536     }
    537 
    538     if (fParent->fFirstChild == this) {
    539         fParent->fFirstChild = next;
    540     }
    541 
    542     fParent = fNextSibling = fPrevSibling = NULL;
    543 
    544     this->validate();
    545     this->unref();
    546 }
    547 
    548 void SkView::detachFromParent() {
    549     this->validate();
    550     SkView* parent = fParent;
    551 
    552     if (parent) {
    553         this->detachFromParent_NoLayout();
    554         parent->invokeLayout();
    555     }
    556 }
    557 
    558 SkView* SkView::attachChildToBack(SkView* child) {
    559     this->validate();
    560     SkASSERT(child != this);
    561 
    562     if (child == NULL || fFirstChild == child)
    563         goto DONE;
    564 
    565     child->ref();
    566     child->detachFromParent_NoLayout();
    567 
    568     if (fFirstChild == NULL) {
    569         child->fNextSibling = child;
    570         child->fPrevSibling = child;
    571     } else {
    572         child->fNextSibling = fFirstChild;
    573         child->fPrevSibling = fFirstChild->fPrevSibling;
    574         fFirstChild->fPrevSibling->fNextSibling = child;
    575         fFirstChild->fPrevSibling = child;
    576     }
    577 
    578     fFirstChild = child;
    579     child->fParent = this;
    580     child->inval(NULL);
    581 
    582     this->validate();
    583     this->invokeLayout();
    584 DONE:
    585     return child;
    586 }
    587 
    588 SkView* SkView::attachChildToFront(SkView* child) {
    589     this->validate();
    590     SkASSERT(child != this);
    591 
    592     if (child == NULL || (fFirstChild && fFirstChild->fPrevSibling == child))
    593         goto DONE;
    594 
    595     child->ref();
    596     child->detachFromParent_NoLayout();
    597 
    598     if (fFirstChild == NULL) {
    599         fFirstChild = child;
    600         child->fNextSibling = child;
    601         child->fPrevSibling = child;
    602     } else {
    603         child->fNextSibling = fFirstChild;
    604         child->fPrevSibling = fFirstChild->fPrevSibling;
    605         fFirstChild->fPrevSibling->fNextSibling = child;
    606         fFirstChild->fPrevSibling = child;
    607     }
    608 
    609     child->fParent = this;
    610     child->inval(NULL);
    611 
    612     this->validate();
    613     this->invokeLayout();
    614 DONE:
    615     return child;
    616 }
    617 
    618 void SkView::detachAllChildren() {
    619     this->validate();
    620     while (fFirstChild)
    621         fFirstChild->detachFromParent_NoLayout();
    622 }
    623 
    624 void SkView::localToGlobal(SkMatrix* matrix) const {
    625     if (matrix) {
    626         matrix->reset();
    627         const SkView* view = this;
    628         while (view)
    629         {
    630             matrix->preConcat(view->getLocalMatrix());
    631             matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY);
    632             view = view->fParent;
    633         }
    634     }
    635 }
    636 bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const
    637 {
    638     SkASSERT(this);
    639 
    640     if (local) {
    641         SkMatrix m;
    642         this->localToGlobal(&m);
    643         if (!m.invert(&m)) {
    644             return false;
    645         }
    646         SkPoint p;
    647         m.mapXY(x, y, &p);
    648         local->set(p.fX, p.fY);
    649     }
    650 
    651     return true;
    652 }
    653 
    654 //////////////////////////////////////////////////////////////////
    655 
    656 /*    Even if the subclass overrides onInflate, they should always be
    657     sure to call the inherited method, so that we get called.
    658 */
    659 void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) {
    660     SkScalar x, y;
    661 
    662     x = this->locX();
    663     y = this->locY();
    664     (void)dom.findScalar(node, "x", &x);
    665     (void)dom.findScalar(node, "y", &y);
    666     this->setLoc(x, y);
    667 
    668     x = this->width();
    669     y = this->height();
    670     (void)dom.findScalar(node, "width", &x);
    671     (void)dom.findScalar(node, "height", &y);
    672     this->setSize(x, y);
    673 
    674     // inflate the flags
    675 
    676     static const char* gFlagNames[] = {
    677         "visible", "enabled", "focusable", "flexH", "flexV"
    678     };
    679     SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount);
    680 
    681     bool     b;
    682     uint32_t flags = this->getFlags();
    683     for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++)
    684         if (dom.findBool(node, gFlagNames[i], &b))
    685             flags = SkSetClearShift(flags, b, i);
    686     this->setFlags(flags);
    687 }
    688 
    689 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) {
    690     this->onInflate(dom, node);
    691 }
    692 
    693 void SkView::onPostInflate(const SkTDict<SkView*>&) {
    694     // override in subclass as needed
    695 }
    696 
    697 void SkView::postInflate(const SkTDict<SkView*>& dict) {
    698     this->onPostInflate(dict);
    699 
    700     B2FIter    iter(this);
    701     SkView*    child;
    702     while ((child = iter.next()) != NULL)
    703         child->postInflate(dict);
    704 }
    705 
    706 //////////////////////////////////////////////////////////////////
    707 
    708 SkView* SkView::sendEventToParents(const SkEvent& evt) {
    709     SkView* parent = fParent;
    710 
    711     while (parent) {
    712         if (parent->doEvent(evt)) {
    713             return parent;
    714         }
    715         parent = parent->fParent;
    716     }
    717     return NULL;
    718 }
    719 
    720 SkView* SkView::sendQueryToParents(SkEvent* evt) {
    721     SkView* parent = fParent;
    722 
    723     while (parent) {
    724         if (parent->doQuery(evt)) {
    725             return parent;
    726         }
    727         parent = parent->fParent;
    728     }
    729     return NULL;
    730 }
    731 
    732 //////////////////////////////////////////////////////////////////
    733 //////////////////////////////////////////////////////////////////
    734 
    735 SkView::F2BIter::F2BIter(const SkView* parent) {
    736     fFirstChild = parent ? parent->fFirstChild : NULL;
    737     fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL;
    738 }
    739 
    740 SkView* SkView::F2BIter::next() {
    741     SkView* curr = fChild;
    742 
    743     if (fChild) {
    744         if (fChild == fFirstChild) {
    745             fChild = NULL;
    746         } else {
    747             fChild = fChild->fPrevSibling;
    748         }
    749     }
    750     return curr;
    751 }
    752 
    753 SkView::B2FIter::B2FIter(const SkView* parent) {
    754     fFirstChild = parent ? parent->fFirstChild : NULL;
    755     fChild = fFirstChild;
    756 }
    757 
    758 SkView* SkView::B2FIter::next() {
    759     SkView* curr = fChild;
    760 
    761     if (fChild) {
    762         SkView* next = fChild->fNextSibling;
    763         if (next == fFirstChild)
    764             next = NULL;
    765         fChild = next;
    766     }
    767     return curr;
    768 }
    769 
    770 //////////////////////////////////////////////////////////////////
    771 //////////////////////////////////////////////////////////////////
    772 
    773 #ifdef SK_DEBUG
    774 
    775 void SkView::validate() const {
    776 //    SkASSERT(this->getRefCnt() > 0 && this->getRefCnt() < 100);
    777     if (fParent) {
    778         SkASSERT(fNextSibling);
    779         SkASSERT(fPrevSibling);
    780     } else {
    781         bool nextNull = NULL == fNextSibling;
    782         bool prevNull = NULL == fNextSibling;
    783         SkASSERT(nextNull == prevNull);
    784     }
    785 }
    786 
    787 static inline void show_if_nonzero(const char name[], SkScalar value)
    788 {
    789     if (value)
    790         SkDebugf("%s=\"%g\"", name, value/65536.);
    791 }
    792 
    793 static void tab(int level)
    794 {
    795     for (int i = 0; i < level; i++)
    796         SkDebugf("    ");
    797 }
    798 
    799 static void dumpview(const SkView* view, int level, bool recurse)
    800 {
    801     tab(level);
    802 
    803     SkDebugf("<view");
    804     show_if_nonzero(" x", view->locX());
    805     show_if_nonzero(" y", view->locY());
    806     show_if_nonzero(" width", view->width());
    807     show_if_nonzero(" height", view->height());
    808 
    809     if (recurse)
    810     {
    811         SkView::B2FIter    iter(view);
    812         SkView*            child;
    813         bool            noChildren = true;
    814 
    815         while ((child = iter.next()) != NULL)
    816         {
    817             if (noChildren)
    818                 SkDebugf(">\n");
    819             noChildren = false;
    820             dumpview(child, level + 1, true);
    821         }
    822 
    823         if (!noChildren)
    824         {
    825             tab(level);
    826             SkDebugf("</view>\n");
    827         }
    828         else
    829             goto ONELINER;
    830     }
    831     else
    832     {
    833     ONELINER:
    834         SkDebugf(" />\n");
    835     }
    836 }
    837 
    838 void SkView::dump(bool recurse) const
    839 {
    840     dumpview(this, 0, recurse);
    841 }
    842 
    843 #endif
    844