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