aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/views/SkViewInflate.cpp
blob: 8f5489de546f42704a6cef56add7cad0dcc845f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "SkViewInflate.h"
#include "SkView.h"
#include <stdio.h>

SkViewInflate::SkViewInflate() : fIDs(kMinIDStrAlloc), fStrings(kMinIDStrAlloc)
{
}

SkViewInflate::~SkViewInflate()
{
}

void SkViewInflate::rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent)
{
	const char* str = dom.findAttr(node, "id");
	if (str)
		fIDs.set(str, parent);

	const SkDOM::Node* child = dom.getFirstChild(node);
	while (child)
	{
		SkView* view = this->createView(dom, child);
		if (view)
		{
			this->rInflate(dom, child, view);
			parent->attachChildToFront(view)->unref();
		}
		else
		{
			const char* name = dom.getName(child);
			const char* target;

			if (!strcmp(name, "listenTo") && (target = dom.findAttr(child, "target")) != NULL)
				this->addIDStr(&fListenTo, parent, target);

			if (!strcmp(name, "broadcastTo") && (target = dom.findAttr(child, "target")) != NULL)
				this->addIDStr(&fBroadcastTo, parent, target);
		}
		child = dom.getNextSibling(child);
	}

	parent->setVisibleP(true);
	this->inflateView(parent, dom, node);
}

void SkViewInflate::inflateView(SkView* view, const SkDOM& dom, const SkDOM::Node* node)
{
	// called after all of view's children have been instantiated.
	// this may be overridden by a subclass, to load in layout or other helpers
	// they should call through to us (INHERITED) before or after their patch
	view->inflate(dom, node);
}

SkView* SkViewInflate::inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root)
{
	fIDs.reset();

	if (root == NULL)
	{
		root = this->createView(dom, node);
		if (root == NULL)
		{
			printf("createView returned NULL on <%s>\n", dom.getName(node));
			return NULL;
		}
	}
	this->rInflate(dom, node, root);

	// resolve listeners and broadcasters
	{
		SkView*			target;
		const IDStr*	iter = fListenTo.begin();
		const IDStr*	stop = fListenTo.end();
		for (; iter < stop; iter++)
		{
			if (fIDs.find(iter->fStr, &target))
				target->addListenerID(iter->fView->getSinkID());
		}

		iter = fBroadcastTo.begin();
		stop = fBroadcastTo.end();
		for (; iter < stop; iter++)
		{
			if (fIDs.find(iter->fStr, &target))
				iter->fView->addListenerID(target->getSinkID());
		}
	}

	// now that the tree is built, give everyone a shot at the ID dict
	root->postInflate(fIDs);
	return root;
}

SkView* SkViewInflate::inflate(const char xml[], size_t len, SkView* root)
{
	SkDOM				dom;
	const SkDOM::Node*	node = dom.build(xml, len);

	return node ? this->inflate(dom, node, root) : NULL;
}

SkView* SkViewInflate::findViewByID(const char id[]) const
{
	SkASSERT(id);
	SkView* view;
	return fIDs.find(id, &view) ? view : NULL;
}

SkView* SkViewInflate::createView(const SkDOM& dom, const SkDOM::Node* node)
{
	if (!strcmp(dom.getName(node), "view"))
		return new SkView;
	return NULL;
}

void SkViewInflate::addIDStr(SkTDArray<IDStr>* list, SkView* view, const char* str)
{
	size_t len = strlen(str) + 1;
	IDStr* pair = list->append();
	pair->fView = view;
	pair->fStr = (char*)fStrings.alloc(len, SkChunkAlloc::kThrow_AllocFailType);
	memcpy(pair->fStr, str, len);
}

#ifdef SK_DEBUG
void SkViewInflate::dump() const
{
	const IDStr* iter = fListenTo.begin();
	const IDStr* stop = fListenTo.end();
	for (; iter < stop; iter++)
		SkDebugf("inflate: listenTo(\"%s\")\n", iter->fStr);

	iter = fBroadcastTo.begin();
	stop = fBroadcastTo.end();
	for (; iter < stop; iter++)
		SkDebugf("inflate: broadcastFrom(\"%s\")\n", iter->fStr);
}
#endif