aboutsummaryrefslogtreecommitdiffstats
path: root/src/views/SkViewInflate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/views/SkViewInflate.cpp')
-rw-r--r--src/views/SkViewInflate.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/views/SkViewInflate.cpp b/src/views/SkViewInflate.cpp
new file mode 100644
index 0000000..8f5489d
--- /dev/null
+++ b/src/views/SkViewInflate.cpp
@@ -0,0 +1,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
+