michael@0: michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: #include "SkViewInflate.h" michael@0: #include "SkView.h" michael@0: #include michael@0: michael@0: SkViewInflate::SkViewInflate() : fIDs(kMinIDStrAlloc), fStrings(kMinIDStrAlloc) michael@0: { michael@0: } michael@0: michael@0: SkViewInflate::~SkViewInflate() michael@0: { michael@0: } michael@0: michael@0: void SkViewInflate::rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent) michael@0: { michael@0: const char* str = dom.findAttr(node, "id"); michael@0: if (str) michael@0: fIDs.set(str, parent); michael@0: michael@0: const SkDOM::Node* child = dom.getFirstChild(node); michael@0: while (child) michael@0: { michael@0: SkView* view = this->createView(dom, child); michael@0: if (view) michael@0: { michael@0: this->rInflate(dom, child, view); michael@0: parent->attachChildToFront(view)->unref(); michael@0: } michael@0: else michael@0: { michael@0: const char* name = dom.getName(child); michael@0: const char* target; michael@0: michael@0: if (!strcmp(name, "listenTo") && (target = dom.findAttr(child, "target")) != NULL) michael@0: this->addIDStr(&fListenTo, parent, target); michael@0: michael@0: if (!strcmp(name, "broadcastTo") && (target = dom.findAttr(child, "target")) != NULL) michael@0: this->addIDStr(&fBroadcastTo, parent, target); michael@0: } michael@0: child = dom.getNextSibling(child); michael@0: } michael@0: michael@0: parent->setVisibleP(true); michael@0: this->inflateView(parent, dom, node); michael@0: } michael@0: michael@0: void SkViewInflate::inflateView(SkView* view, const SkDOM& dom, const SkDOM::Node* node) michael@0: { michael@0: // called after all of view's children have been instantiated. michael@0: // this may be overridden by a subclass, to load in layout or other helpers michael@0: // they should call through to us (INHERITED) before or after their patch michael@0: view->inflate(dom, node); michael@0: } michael@0: michael@0: SkView* SkViewInflate::inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root) michael@0: { michael@0: fIDs.reset(); michael@0: michael@0: if (root == NULL) michael@0: { michael@0: root = this->createView(dom, node); michael@0: if (root == NULL) michael@0: { michael@0: printf("createView returned NULL on <%s>\n", dom.getName(node)); michael@0: return NULL; michael@0: } michael@0: } michael@0: this->rInflate(dom, node, root); michael@0: michael@0: // resolve listeners and broadcasters michael@0: { michael@0: SkView* target; michael@0: const IDStr* iter = fListenTo.begin(); michael@0: const IDStr* stop = fListenTo.end(); michael@0: for (; iter < stop; iter++) michael@0: { michael@0: if (fIDs.find(iter->fStr, &target)) michael@0: target->addListenerID(iter->fView->getSinkID()); michael@0: } michael@0: michael@0: iter = fBroadcastTo.begin(); michael@0: stop = fBroadcastTo.end(); michael@0: for (; iter < stop; iter++) michael@0: { michael@0: if (fIDs.find(iter->fStr, &target)) michael@0: iter->fView->addListenerID(target->getSinkID()); michael@0: } michael@0: } michael@0: michael@0: // now that the tree is built, give everyone a shot at the ID dict michael@0: root->postInflate(fIDs); michael@0: return root; michael@0: } michael@0: michael@0: SkView* SkViewInflate::inflate(const char xml[], size_t len, SkView* root) michael@0: { michael@0: SkDOM dom; michael@0: const SkDOM::Node* node = dom.build(xml, len); michael@0: michael@0: return node ? this->inflate(dom, node, root) : NULL; michael@0: } michael@0: michael@0: SkView* SkViewInflate::findViewByID(const char id[]) const michael@0: { michael@0: SkASSERT(id); michael@0: SkView* view; michael@0: return fIDs.find(id, &view) ? view : NULL; michael@0: } michael@0: michael@0: SkView* SkViewInflate::createView(const SkDOM& dom, const SkDOM::Node* node) michael@0: { michael@0: if (!strcmp(dom.getName(node), "view")) michael@0: return new SkView; michael@0: return NULL; michael@0: } michael@0: michael@0: void SkViewInflate::addIDStr(SkTDArray* list, SkView* view, const char* str) michael@0: { michael@0: size_t len = strlen(str) + 1; michael@0: IDStr* pair = list->append(); michael@0: pair->fView = view; michael@0: pair->fStr = (char*)fStrings.alloc(len, SkChunkAlloc::kThrow_AllocFailType); michael@0: memcpy(pair->fStr, str, len); michael@0: } michael@0: michael@0: #ifdef SK_DEBUG michael@0: void SkViewInflate::dump() const michael@0: { michael@0: const IDStr* iter = fListenTo.begin(); michael@0: const IDStr* stop = fListenTo.end(); michael@0: for (; iter < stop; iter++) michael@0: SkDebugf("inflate: listenTo(\"%s\")\n", iter->fStr); michael@0: michael@0: iter = fBroadcastTo.begin(); michael@0: stop = fBroadcastTo.end(); michael@0: for (; iter < stop; iter++) michael@0: SkDebugf("inflate: broadcastFrom(\"%s\")\n", iter->fStr); michael@0: } michael@0: #endif