Home | History | Annotate | Download | only in views
      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")) != NULL)
     41 				this->addIDStr(&fListenTo, parent, target);
     42 
     43 			if (!strcmp(name, "broadcastTo") && (target = dom.findAttr(child, "target")) != NULL)
     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 == NULL)
     66 	{
     67 		root = this->createView(dom, node);
     68 		if (root == NULL)
     69 		{
     70 			printf("createView returned NULL on <%s>\n", dom.getName(node));
     71 			return NULL;
     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) : NULL;
    107 }
    108 
    109 SkView* SkViewInflate::findViewByID(const char id[]) const
    110 {
    111 	SkASSERT(id);
    112 	SkView* view;
    113 	return fIDs.find(id, &view) ? view : NULL;
    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 NULL;
    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 
    147