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