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