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