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