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