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