1 #include "SkViewInflate.h" 2 #include "SkView.h" 3 #include <stdio.h> 4 5 SkViewInflate::SkViewInflate() : fIDs(kMinIDStrAlloc), fStrings(kMinIDStrAlloc) 6 { 7 } 8 9 SkViewInflate::~SkViewInflate() 10 { 11 } 12 13 void 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 46 void 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 54 SkView* 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 94 SkView* 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 102 SkView* SkViewInflate::findViewByID(const char id[]) const 103 { 104 SkASSERT(id); 105 SkView* view; 106 return fIDs.find(id, &view) ? view : NULL; 107 } 108 109 SkView* 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 116 void 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 126 void 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 140