| |
| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #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 |