blob: 8f5489de546f42704a6cef56add7cad0dcc845f0 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkViewInflate.h"
2#include "SkView.h"
3#include <stdio.h>
4
5SkViewInflate::SkViewInflate() : fIDs(kMinIDStrAlloc), fStrings(kMinIDStrAlloc)
6{
7}
8
9SkViewInflate::~SkViewInflate()
10{
11}
12
13void SkViewInflate::rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent)
14{
15 const char* str = dom.findAttr(node, "id");
16 if (str)
17 fIDs.set(str, parent);
18
19 const SkDOM::Node* child = dom.getFirstChild(node);
20 while (child)
21 {
22 SkView* view = this->createView(dom, child);
23 if (view)
24 {
25 this->rInflate(dom, child, view);
26 parent->attachChildToFront(view)->unref();
27 }
28 else
29 {
30 const char* name = dom.getName(child);
31 const char* target;
32
33 if (!strcmp(name, "listenTo") && (target = dom.findAttr(child, "target")) != NULL)
34 this->addIDStr(&fListenTo, parent, target);
35
36 if (!strcmp(name, "broadcastTo") && (target = dom.findAttr(child, "target")) != NULL)
37 this->addIDStr(&fBroadcastTo, parent, target);
38 }
39 child = dom.getNextSibling(child);
40 }
41
42 parent->setVisibleP(true);
43 this->inflateView(parent, dom, node);
44}
45
46void SkViewInflate::inflateView(SkView* view, const SkDOM& dom, const SkDOM::Node* node)
47{
48 // called after all of view's children have been instantiated.
49 // this may be overridden by a subclass, to load in layout or other helpers
50 // they should call through to us (INHERITED) before or after their patch
51 view->inflate(dom, node);
52}
53
54SkView* SkViewInflate::inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root)
55{
56 fIDs.reset();
57
58 if (root == NULL)
59 {
60 root = this->createView(dom, node);
61 if (root == NULL)
62 {
63 printf("createView returned NULL on <%s>\n", dom.getName(node));
64 return NULL;
65 }
66 }
67 this->rInflate(dom, node, root);
68
69 // resolve listeners and broadcasters
70 {
71 SkView* target;
72 const IDStr* iter = fListenTo.begin();
73 const IDStr* stop = fListenTo.end();
74 for (; iter < stop; iter++)
75 {
76 if (fIDs.find(iter->fStr, &target))
77 target->addListenerID(iter->fView->getSinkID());
78 }
79
80 iter = fBroadcastTo.begin();
81 stop = fBroadcastTo.end();
82 for (; iter < stop; iter++)
83 {
84 if (fIDs.find(iter->fStr, &target))
85 iter->fView->addListenerID(target->getSinkID());
86 }
87 }
88
89 // now that the tree is built, give everyone a shot at the ID dict
90 root->postInflate(fIDs);
91 return root;
92}
93
94SkView* SkViewInflate::inflate(const char xml[], size_t len, SkView* root)
95{
96 SkDOM dom;
97 const SkDOM::Node* node = dom.build(xml, len);
98
99 return node ? this->inflate(dom, node, root) : NULL;
100}
101
102SkView* SkViewInflate::findViewByID(const char id[]) const
103{
104 SkASSERT(id);
105 SkView* view;
106 return fIDs.find(id, &view) ? view : NULL;
107}
108
109SkView* SkViewInflate::createView(const SkDOM& dom, const SkDOM::Node* node)
110{
111 if (!strcmp(dom.getName(node), "view"))
112 return new SkView;
113 return NULL;
114}
115
116void SkViewInflate::addIDStr(SkTDArray<IDStr>* list, SkView* view, const char* str)
117{
118 size_t len = strlen(str) + 1;
119 IDStr* pair = list->append();
120 pair->fView = view;
121 pair->fStr = (char*)fStrings.alloc(len, SkChunkAlloc::kThrow_AllocFailType);
122 memcpy(pair->fStr, str, len);
123}
124
125#ifdef SK_DEBUG
126void SkViewInflate::dump() const
127{
128 const IDStr* iter = fListenTo.begin();
129 const IDStr* stop = fListenTo.end();
130 for (; iter < stop; iter++)
131 SkDebugf("inflate: listenTo(\"%s\")\n", iter->fStr);
132
133 iter = fBroadcastTo.begin();
134 stop = fBroadcastTo.end();
135 for (; iter < stop; iter++)
136 SkDebugf("inflate: broadcastFrom(\"%s\")\n", iter->fStr);
137}
138#endif
139