• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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