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