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, SkCanvas::kBW_EdgeType)) {
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)372 SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y)
373 {
374 if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
375 return NULL;
376 }
377
378 if (this->onSendClickToChildren(x, y)) {
379 F2BIter iter(this);
380 SkView* child;
381
382 while ((child = iter.next()) != NULL)
383 {
384 SkPoint p;
385 child->globalToLocal(x, y, &p);
386
387 Click* click = child->findClickHandler(p.fX, p.fY);
388
389 if (click) {
390 return click;
391 }
392 }
393 }
394 return this->onFindClickHandler(x, y);
395 }
396
DoClickDown(Click * click,int x,int y)397 void SkView::DoClickDown(Click* click, int x, int y)
398 {
399 SkASSERT(click);
400
401 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
402 if (target == NULL)
403 return;
404
405 click->fIOrig.set(x, y);
406 click->fICurr = click->fIPrev = click->fIOrig;
407
408 click->fOrig.iset(x, y);
409 target->globalToLocal(&click->fOrig);
410 click->fPrev = click->fCurr = click->fOrig;
411
412 click->fState = Click::kDown_State;
413 target->onClick(click);
414 }
415
DoClickMoved(Click * click,int x,int y)416 void SkView::DoClickMoved(Click* click, int x, int y)
417 {
418 SkASSERT(click);
419
420 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
421 if (target == NULL)
422 return;
423
424 click->fIPrev = click->fICurr;
425 click->fICurr.set(x, y);
426
427 click->fPrev = click->fCurr;
428 click->fCurr.iset(x, y);
429 target->globalToLocal(&click->fCurr);
430
431 click->fState = Click::kMoved_State;
432 target->onClick(click);
433 }
434
DoClickUp(Click * click,int x,int y)435 void SkView::DoClickUp(Click* click, int x, int y)
436 {
437 SkASSERT(click);
438
439 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
440 if (target == NULL)
441 return;
442
443 click->fIPrev = click->fICurr;
444 click->fICurr.set(x, y);
445
446 click->fPrev = click->fCurr;
447 click->fCurr.iset(x, y);
448 target->globalToLocal(&click->fCurr);
449
450 click->fState = Click::kUp_State;
451 target->onClick(click);
452 }
453
454 //////////////////////////////////////////////////////////////////////
455
invokeLayout()456 void SkView::invokeLayout() {
457 SkView::Layout* layout = this->getLayout();
458
459 if (layout) {
460 layout->layoutChildren(this);
461 }
462 }
463
onDraw(SkCanvas * canvas)464 void SkView::onDraw(SkCanvas* canvas) {
465 Artist* artist = this->getArtist();
466
467 if (artist) {
468 artist->draw(this, canvas);
469 }
470 }
471
onSizeChange()472 void SkView::onSizeChange() {}
473
onSendClickToChildren(SkScalar x,SkScalar y)474 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y) {
475 return true;
476 }
477
onFindClickHandler(SkScalar x,SkScalar y)478 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y) {
479 return NULL;
480 }
481
onClick(Click *)482 bool SkView::onClick(Click*) {
483 return false;
484 }
485
handleInval(const SkRect *)486 bool SkView::handleInval(const SkRect*) {
487 return false;
488 }
489
490 //////////////////////////////////////////////////////////////////////
491
getLocalBounds(SkRect * bounds) const492 void SkView::getLocalBounds(SkRect* bounds) const
493 {
494 if (bounds)
495 bounds->set(0, 0, fWidth, fHeight);
496 }
497
498 //////////////////////////////////////////////////////////////////////
499 //////////////////////////////////////////////////////////////////////
500
detachFromParent_NoLayout()501 void SkView::detachFromParent_NoLayout()
502 {
503 if (fParent == NULL)
504 return;
505
506 if (fContainsFocus)
507 (void)this->setFocusView(NULL);
508
509 this->inval(NULL);
510
511 SkView* next = NULL;
512
513 if (fNextSibling != this) // do we have any siblings
514 {
515 fNextSibling->fPrevSibling = fPrevSibling;
516 fPrevSibling->fNextSibling = fNextSibling;
517 next = fNextSibling;
518 }
519
520 if (fParent->fFirstChild == this)
521 fParent->fFirstChild = next;
522
523 fParent = fNextSibling = fPrevSibling = NULL;
524
525 this->unref();
526 }
527
detachFromParent()528 void SkView::detachFromParent()
529 {
530 SkView* parent = fParent;
531
532 if (parent)
533 {
534 this->detachFromParent_NoLayout();
535 parent->invokeLayout();
536 }
537 }
538
attachChildToBack(SkView * child)539 SkView* SkView::attachChildToBack(SkView* child)
540 {
541 SkASSERT(child != this);
542
543 if (child == NULL || fFirstChild == child)
544 goto DONE;
545
546 child->ref();
547 child->detachFromParent_NoLayout();
548
549 if (fFirstChild == NULL)
550 {
551 child->fNextSibling = child;
552 child->fPrevSibling = child;
553 }
554 else
555 {
556 child->fNextSibling = fFirstChild;
557 child->fPrevSibling = fFirstChild->fPrevSibling;
558 fFirstChild->fPrevSibling->fNextSibling = child;
559 fFirstChild->fPrevSibling = child;
560 }
561
562 fFirstChild = child;
563 child->fParent = this;
564 child->inval(NULL);
565
566 this->invokeLayout();
567 DONE:
568 return child;
569 }
570
attachChildToFront(SkView * child)571 SkView* SkView::attachChildToFront(SkView* child)
572 {
573 SkASSERT(child != this);
574
575 if (child == NULL || (fFirstChild && fFirstChild->fPrevSibling == child))
576 goto DONE;
577
578 child->ref();
579 child->detachFromParent_NoLayout();
580
581 if (fFirstChild == NULL)
582 {
583 fFirstChild = child;
584 child->fNextSibling = child;
585 child->fPrevSibling = child;
586 }
587 else
588 {
589 child->fNextSibling = fFirstChild;
590 child->fPrevSibling = fFirstChild->fPrevSibling;
591 fFirstChild->fPrevSibling->fNextSibling = child;
592 fFirstChild->fPrevSibling = child;
593 }
594
595 child->fParent = this;
596 child->inval(NULL);
597
598 this->invokeLayout();
599 DONE:
600 return child;
601 }
602
detachAllChildren()603 void SkView::detachAllChildren()
604 {
605 while (fFirstChild)
606 fFirstChild->detachFromParent_NoLayout();
607 }
608
localToGlobal(SkMatrix * matrix) const609 void SkView::localToGlobal(SkMatrix* matrix) const
610 {
611 if (matrix) {
612 matrix->reset();
613 const SkView* view = this;
614 while (view)
615 {
616 matrix->preConcat(view->getLocalMatrix());
617 matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY);
618 view = view->fParent;
619 }
620 }
621 }
globalToLocal(SkScalar x,SkScalar y,SkPoint * local) const622 void SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const
623 {
624 SkASSERT(this);
625 if (local)
626 {
627 SkMatrix m;
628 this->localToGlobal(&m);
629 SkPoint p;
630 m.invert(&m);
631 m.mapXY(x, y, &p);
632 local->set(p.fX, p.fY);
633 }
634 }
635
636 //////////////////////////////////////////////////////////////////
637
638 /* Even if the subclass overrides onInflate, they should always be
639 sure to call the inherited method, so that we get called.
640 */
onInflate(const SkDOM & dom,const SkDOM::Node * node)641 void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
642 {
643 SkScalar x, y;
644
645 x = this->locX();
646 y = this->locY();
647 (void)dom.findScalar(node, "x", &x);
648 (void)dom.findScalar(node, "y", &y);
649 this->setLoc(x, y);
650
651 x = this->width();
652 y = this->height();
653 (void)dom.findScalar(node, "width", &x);
654 (void)dom.findScalar(node, "height", &y);
655 this->setSize(x, y);
656
657 // inflate the flags
658
659 static const char* gFlagNames[] = {
660 "visible", "enabled", "focusable", "flexH", "flexV"
661 };
662 SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount);
663
664 bool b;
665 uint32_t flags = this->getFlags();
666 for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++)
667 if (dom.findBool(node, gFlagNames[i], &b))
668 flags = SkSetClearShift(flags, b, i);
669 this->setFlags(flags);
670 }
671
inflate(const SkDOM & dom,const SkDOM::Node * node)672 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node)
673 {
674 this->onInflate(dom, node);
675 }
676
onPostInflate(const SkTDict<SkView * > &)677 void SkView::onPostInflate(const SkTDict<SkView*>&)
678 {
679 // override in subclass as needed
680 }
681
postInflate(const SkTDict<SkView * > & dict)682 void SkView::postInflate(const SkTDict<SkView*>& dict)
683 {
684 this->onPostInflate(dict);
685
686 B2FIter iter(this);
687 SkView* child;
688 while ((child = iter.next()) != NULL)
689 child->postInflate(dict);
690 }
691
692 //////////////////////////////////////////////////////////////////
693
sendEventToParents(const SkEvent & evt)694 SkView* SkView::sendEventToParents(const SkEvent& evt)
695 {
696 SkView* parent = fParent;
697
698 while (parent)
699 {
700 if (parent->doEvent(evt))
701 return parent;
702 parent = parent->fParent;
703 }
704 return NULL;
705 }
706
sendQueryToParents(SkEvent * evt)707 SkView* SkView::sendQueryToParents(SkEvent* evt) {
708 SkView* parent = fParent;
709
710 while (parent) {
711 if (parent->doQuery(evt)) {
712 return parent;
713 }
714 parent = parent->fParent;
715 }
716 return NULL;
717 }
718
719 //////////////////////////////////////////////////////////////////
720 //////////////////////////////////////////////////////////////////
721
F2BIter(const SkView * parent)722 SkView::F2BIter::F2BIter(const SkView* parent)
723 {
724 fFirstChild = parent ? parent->fFirstChild : NULL;
725 fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL;
726 }
727
next()728 SkView* SkView::F2BIter::next()
729 {
730 SkView* curr = fChild;
731
732 if (fChild)
733 {
734 if (fChild == fFirstChild)
735 fChild = NULL;
736 else
737 fChild = fChild->fPrevSibling;
738 }
739 return curr;
740 }
741
B2FIter(const SkView * parent)742 SkView::B2FIter::B2FIter(const SkView* parent)
743 {
744 fFirstChild = parent ? parent->fFirstChild : NULL;
745 fChild = fFirstChild;
746 }
747
next()748 SkView* SkView::B2FIter::next()
749 {
750 SkView* curr = fChild;
751
752 if (fChild)
753 {
754 SkView* next = fChild->fNextSibling;
755 if (next == fFirstChild)
756 next = NULL;
757 fChild = next;
758 }
759 return curr;
760 }
761
762 //////////////////////////////////////////////////////////////////
763 //////////////////////////////////////////////////////////////////
764
765 #ifdef SK_DEBUG
766
show_if_nonzero(const char name[],SkScalar value)767 static inline void show_if_nonzero(const char name[], SkScalar value)
768 {
769 if (value)
770 SkDebugf("%s=\"%g\"", name, value/65536.);
771 }
772
tab(int level)773 static void tab(int level)
774 {
775 for (int i = 0; i < level; i++)
776 SkDebugf(" ");
777 }
778
dumpview(const SkView * view,int level,bool recurse)779 static void dumpview(const SkView* view, int level, bool recurse)
780 {
781 tab(level);
782
783 SkDebugf("<view");
784 show_if_nonzero(" x", view->locX());
785 show_if_nonzero(" y", view->locY());
786 show_if_nonzero(" width", view->width());
787 show_if_nonzero(" height", view->height());
788
789 if (recurse)
790 {
791 SkView::B2FIter iter(view);
792 SkView* child;
793 bool noChildren = true;
794
795 while ((child = iter.next()) != NULL)
796 {
797 if (noChildren)
798 SkDebugf(">\n");
799 noChildren = false;
800 dumpview(child, level + 1, true);
801 }
802
803 if (!noChildren)
804 {
805 tab(level);
806 SkDebugf("</view>\n");
807 }
808 else
809 goto ONELINER;
810 }
811 else
812 {
813 ONELINER:
814 SkDebugf(" />\n");
815 }
816 }
817
dump(bool recurse) const818 void SkView::dump(bool recurse) const
819 {
820 dumpview(this, 0, recurse);
821 }
822
823 #endif
824