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