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
13SkView::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
22SkView::~SkView()
23{
24	this->detachAllChildren();
25}
26
27void 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
44void SkView::setVisibleP(bool pred)
45{
46	this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift));
47}
48
49void SkView::setEnabledP(bool pred)
50{
51	this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift));
52}
53
54void SkView::setFocusableP(bool pred)
55{
56	this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
57}
58
59void SkView::setClipToBounds(bool pred) {
60    this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
61}
62
63void 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
79void 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
89void SkView::offset(SkScalar dx, SkScalar dy)
90{
91	if (dx || dy)
92		this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
93}
94
95void SkView::setLocalMatrix(const SkMatrix& matrix)
96{
97    this->inval(NULL);
98    fMatrix = matrix;
99    this->inval(NULL);
100}
101
102void 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
146void 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
181bool 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
192SkView* 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
203bool SkView::hasFocus() const
204{
205	return this == this->getFocusView();
206}
207
208bool 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*/
216SkView* 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
244SkView* 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
306void SkView::onFocusChange(bool gainFocusP)
307{
308	this->inval(NULL);
309}
310
311////////////////////////////////////////////////////////////////////////////
312
313SkView::Click::Click(SkView* target)
314{
315    SkASSERT(target);
316    fTargetID = target->getSinkID();
317    fType = NULL;
318    fWeOwnTheType = false;
319    fOwner = NULL;
320}
321
322SkView::Click::~Click()
323{
324	this->resetType();
325}
326
327void SkView::Click::resetType()
328{
329	if (fWeOwnTheType)
330	{
331		sk_free(fType);
332		fWeOwnTheType = false;
333	}
334	fType = NULL;
335}
336
337bool 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
351void SkView::Click::setType(const char type[])
352{
353	this->resetType();
354	fType = (char*)type;
355}
356
357void 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
372SkView::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
397void 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
416void 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
435void 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
456void SkView::invokeLayout() {
457	SkView::Layout* layout = this->getLayout();
458
459	if (layout) {
460		layout->layoutChildren(this);
461    }
462}
463
464void SkView::onDraw(SkCanvas* canvas) {
465	Artist* artist = this->getArtist();
466
467	if (artist) {
468		artist->draw(this, canvas);
469    }
470}
471
472void SkView::onSizeChange() {}
473
474bool SkView::onSendClickToChildren(SkScalar x, SkScalar y) {
475    return true;
476}
477
478SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y) {
479	return NULL;
480}
481
482bool SkView::onClick(Click*) {
483	return false;
484}
485
486bool SkView::handleInval(const SkRect*) {
487	return false;
488}
489
490//////////////////////////////////////////////////////////////////////
491
492void SkView::getLocalBounds(SkRect* bounds) const
493{
494	if (bounds)
495		bounds->set(0, 0, fWidth, fHeight);
496}
497
498//////////////////////////////////////////////////////////////////////
499//////////////////////////////////////////////////////////////////////
500
501void 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
528void SkView::detachFromParent()
529{
530	SkView* parent = fParent;
531
532	if (parent)
533	{
534		this->detachFromParent_NoLayout();
535		parent->invokeLayout();
536	}
537}
538
539SkView* 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();
567DONE:
568	return child;
569}
570
571SkView* 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();
599DONE:
600	return child;
601}
602
603void SkView::detachAllChildren()
604{
605	while (fFirstChild)
606		fFirstChild->detachFromParent_NoLayout();
607}
608
609void 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}
622void 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*/
641void 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
672void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node)
673{
674	this->onInflate(dom, node);
675}
676
677void SkView::onPostInflate(const SkTDict<SkView*>&)
678{
679	// override in subclass as needed
680}
681
682void 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
694SkView* 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
707SkView* 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
722SkView::F2BIter::F2BIter(const SkView* parent)
723{
724	fFirstChild = parent ? parent->fFirstChild : NULL;
725	fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL;
726}
727
728SkView*	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
742SkView::B2FIter::B2FIter(const SkView* parent)
743{
744	fFirstChild = parent ? parent->fFirstChild : NULL;
745	fChild = fFirstChild;
746}
747
748SkView*	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
767static inline void show_if_nonzero(const char name[], SkScalar value)
768{
769	if (value)
770		SkDebugf("%s=\"%g\"", name, value/65536.);
771}
772
773static void tab(int level)
774{
775	for (int i = 0; i < level; i++)
776		SkDebugf("    ");
777}
778
779static 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
818void SkView::dump(bool recurse) const
819{
820	dumpview(this, 0, recurse);
821}
822
823#endif
824