SkView.cpp revision 0910916c0f7b951ee55c4b7c6358295b9bca0565
1#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
761