• 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 
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