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 
SkView(uint32_t flags)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 
~SkView()22 SkView::~SkView()
23 {
24     this->detachAllChildren();
25 }
26 
setFlags(uint32_t flags)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 
setVisibleP(bool pred)44 void SkView::setVisibleP(bool pred)
45 {
46     this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift));
47 }
48 
setEnabledP(bool pred)49 void SkView::setEnabledP(bool pred)
50 {
51     this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift));
52 }
53 
setFocusableP(bool pred)54 void SkView::setFocusableP(bool pred)
55 {
56     this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
57 }
58 
setClipToBounds(bool pred)59 void SkView::setClipToBounds(bool pred) {
60     this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
61 }
62 
setSize(SkScalar width,SkScalar height)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 
setLoc(SkScalar x,SkScalar y)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 
offset(SkScalar dx,SkScalar dy)89 void SkView::offset(SkScalar dx, SkScalar dy)
90 {
91     if (dx || dy)
92         this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
93 }
94 
setLocalMatrix(const SkMatrix & matrix)95 void SkView::setLocalMatrix(const SkMatrix& matrix)
96 {
97     this->inval(NULL);
98     fMatrix = matrix;
99     this->inval(NULL);
100 }
101 
draw(SkCanvas * canvas)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 
inval(SkRect * rect)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 
setFocusView(SkView * fv)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 
getFocusView() const192 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 
hasFocus() const203 bool SkView::hasFocus() const
204 {
205     return this == this->getFocusView();
206 }
207 
acceptFocus()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 */
acceptFocus(FocusDirection dir)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 
moveFocus(FocusDirection dir)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 
onFocusChange(bool gainFocusP)306 void SkView::onFocusChange(bool gainFocusP)
307 {
308     this->inval(NULL);
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////
312 
Click(SkView * target)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 
~Click()322 SkView::Click::~Click()
323 {
324     this->resetType();
325 }
326 
resetType()327 void SkView::Click::resetType()
328 {
329     if (fWeOwnTheType)
330     {
331         sk_free(fType);
332         fWeOwnTheType = false;
333     }
334     fType = NULL;
335 }
336 
isType(const char type[]) const337 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 
setType(const char type[])351 void SkView::Click::setType(const char type[])
352 {
353     this->resetType();
354     fType = (char*)type;
355 }
356 
copyType(const char type[])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 
findClickHandler(SkScalar x,SkScalar y,unsigned modi)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 
DoClickDown(Click * click,int x,int y,unsigned modi)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 
DoClickMoved(Click * click,int x,int y,unsigned modi)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 
DoClickUp(Click * click,int x,int y,unsigned modi)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 
invokeLayout()473 void SkView::invokeLayout() {
474     SkView::Layout* layout = this->getLayout();
475 
476     if (layout) {
477         layout->layoutChildren(this);
478     }
479 }
480 
onDraw(SkCanvas * canvas)481 void SkView::onDraw(SkCanvas* canvas) {
482     Artist* artist = this->getArtist();
483 
484     if (artist) {
485         artist->draw(this, canvas);
486     }
487 }
488 
onSizeChange()489 void SkView::onSizeChange() {}
490 
onSendClickToChildren(SkScalar x,SkScalar y,unsigned modi)491 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) {
492     return true;
493 }
494 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)495 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
496     return NULL;
497 }
498 
onClick(Click *)499 bool SkView::onClick(Click*) {
500     return false;
501 }
502 
handleInval(const SkRect *)503 bool SkView::handleInval(const SkRect*) {
504     return false;
505 }
506 
507 //////////////////////////////////////////////////////////////////////
508 
getLocalBounds(SkRect * bounds) const509 void SkView::getLocalBounds(SkRect* bounds) const {
510     if (bounds) {
511         bounds->set(0, 0, fWidth, fHeight);
512     }
513 }
514 
515 //////////////////////////////////////////////////////////////////////
516 //////////////////////////////////////////////////////////////////////
517 
detachFromParent_NoLayout()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 
detachFromParent()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 
attachChildToBack(SkView * child)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 
attachChildToFront(SkView * child)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 
detachAllChildren()618 void SkView::detachAllChildren() {
619     this->validate();
620     while (fFirstChild)
621         fFirstChild->detachFromParent_NoLayout();
622 }
623 
localToGlobal(SkMatrix * matrix) const624 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 }
globalToLocal(SkScalar x,SkScalar y,SkPoint * local) const636 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 */
onInflate(const SkDOM & dom,const SkDOM::Node * node)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 
inflate(const SkDOM & dom,const SkDOM::Node * node)689 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) {
690     this->onInflate(dom, node);
691 }
692 
onPostInflate(const SkTDict<SkView * > &)693 void SkView::onPostInflate(const SkTDict<SkView*>&) {
694     // override in subclass as needed
695 }
696 
postInflate(const SkTDict<SkView * > & dict)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 
sendEventToParents(const SkEvent & evt)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 
sendQueryToParents(SkEvent * evt)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 
F2BIter(const SkView * parent)735 SkView::F2BIter::F2BIter(const SkView* parent) {
736     fFirstChild = parent ? parent->fFirstChild : NULL;
737     fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL;
738 }
739 
next()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 
B2FIter(const SkView * parent)753 SkView::B2FIter::B2FIter(const SkView* parent) {
754     fFirstChild = parent ? parent->fFirstChild : NULL;
755     fChild = fFirstChild;
756 }
757 
next()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 
validate() const775 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 
show_if_nonzero(const char name[],SkScalar value)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 
tab(int level)793 static void tab(int level)
794 {
795     for (int i = 0; i < level; i++)
796         SkDebugf("    ");
797 }
798 
dumpview(const SkView * view,int level,bool recurse)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 
dump(bool recurse) const838 void SkView::dump(bool recurse) const
839 {
840     dumpview(this, 0, recurse);
841 }
842 
843 #endif
844