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