diff pyink/domview.py @ 1301:18af917cf855

Add component_manager as a mix-in of domview
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 19 Jan 2011 01:28:43 +0800
parents 6949e2b6cae2
children c53331c55a23
line wrap: on
line diff
--- a/pyink/domview.py	Sun Jan 16 16:54:21 2011 +0800
+++ b/pyink/domview.py	Wed Jan 19 01:28:43 2011 +0800
@@ -2,6 +2,7 @@
 import dom_event
 from tween import TweenObject
 
+
 class Layer:
     def __init__(self, node):
 	self.scenes = []
@@ -9,6 +10,245 @@
 	pass
     pass
 
+
+class Timeline(object):
+    def __init__(self, scenes_node):
+        self.scenes_node = scenes_node
+        pass
+
+    def name(self):
+        name = self.node.getAttribute('name')
+        return name
+    pass
+
+
+class Component(object):
+    #
+    # \param comp_node is None for main component.
+    #
+    def __init__(self, comp_mgr, comp_node):
+        self._comp_mgr = comp_mgr
+        self.node = comp_node
+        self.layers = []
+        self.timelines = []
+
+        if comp_node:
+            self._initialize_comp()
+            pass
+        pass
+
+    def _initialize_comp(self):
+        comp_node = self.node
+        for child in comp_node.childList():
+            if child.name() == 'ns0:scenes':
+                break
+            pass
+        else:                   # no any ns0:scenes
+            scenes_node = doc.createElementById('ns0:scenes')
+            scenes_node.setAttribute('name', 'default')
+            node_id = self._comp_mgr.new_id()
+            scenes_node.setAttribute('id', node_id)
+            comp_node.appendChild(scenes_node)
+            pass
+        pass
+
+    def name(self):
+        if self.node:
+            name = self.node.getAttribute('name')
+        else:
+            name = 'main'
+            pass
+        return name
+
+    def all_timeline_names(self):
+        names = [tl.name() for tl in self.timelines]
+        return names
+
+    def parse_timelines(self):
+        if self.node:
+            assert self.node.name() == 'ns0:component'
+            pass
+        
+        comp_node = self.node
+        for child in comp_node.childList:
+            if child.name() == 'ns0:scenes':
+                tl = Timeline(child)
+                self.timelines.append(tl)
+                pass
+            pass
+        pass
+
+    def get_timeline(self, name):
+        for tl in self.timelines:
+            if tl.name() == name:
+                return tl
+            pass
+        raise Value, 'invalid timeline name - %s' % (name)
+
+    def has_timeline(self, name):
+        for tl in self.timelines:
+            if tl.name() == name:
+                return True
+            pass
+        return False
+
+    def add_timeline(self, name):
+        if self.has_timeline(name):
+            raise ValueError, \
+                'try add a timeline with duplicated name - %s' % (name)
+        
+        doc = self._comp_mgr._doc
+        comp_node = self.node
+        
+        scenes_node = doc.createElementById('ns0:scenes')
+        scenes_node.setAttribute('name', name)
+        node_id = self._comp_mgr.new_id()
+        scenes_node.setAttribute('id', node_id)
+
+        comp_node.appendChild(scenes_node)
+        pass
+
+    ## \brief Add a timeline for an existed scenes node.
+    #
+    def add_timeline_scenes(self, scenes_node):
+        tl = Timeline(scenes_node)
+        name = tl.name()
+        if self.has_timeline(name):
+            raise ValueError, \
+                'name of scenes node of a timeline is duplicated'
+        pass
+
+    def rm_timeline(self, name):
+        for i, tl in enumerate(self.timelines):
+            if tl.name() == name:
+                del self.timelines[i]
+                return
+            pass
+        raise ValueError, 'try to remove a non-existed timeline - %s' % (name)
+    pass
+
+
+## \brief A mix-in for class domview for management of components.
+#
+class component_manager(object):
+    def __init__(self):
+        self._components = []
+        self._comp_names = set()
+        self._main_comp = None
+        self._cur_comp = None
+        self._cur_timeline = None
+        pass
+
+    def _set_main_component(self):
+        comp = Component(self, None)
+        comp.layers = self._layers
+        scenes_node = self._scenes_node
+        timeline = Timeline(scenes_node)
+        comp.timelines = [timeline]
+
+        self._components.append(comp)
+        self._comp_names.add('main')
+
+        self._main_comp = comp
+        self._cur_comp = comp
+        pass
+
+    def _parse_components(self):
+        comp_names = self._comp_names
+        components_node = self._components_node
+        for child in components_node.childList():
+            child_name = child.name()
+            if child_name != 'ns0:component':
+                continue
+            if child_name in comp_names:
+                raise ValueError, 'duplicate component name %s' % (child_name)
+
+            comp = Component(self, child)
+            comp.parse_timelines()
+            
+            self._components.append(comp)
+            comp_names.add(child_name)
+            pass
+        pass
+    
+    def all_comp_names(self):
+        return list(self._comp_names)
+
+    def has_component(self, name):
+        return name in self._comp_names
+
+    def switch_component(self, comp_name):
+        for comp in self._components:
+            if comp.name() == comp_name:
+                self._cu_comp = comp
+                self._layers = comp.layers
+
+                first_name = comp.all_timeline_names()[0]
+                self.switch_timeline(self, first_name)
+                return
+            pass
+        raise ValueError, 'not such component %s' % (comp_name)
+
+    def add_component(self, comp_name):
+        if self.has_component(comp_name):
+            raise ValueError, \
+                'try add a component with existed name %s' % (comp_name)
+
+        comp_node = self._doc.createElementById('ns0:component')
+        comp_id = self.new_id()
+        comp_node.setAttribute('id', comp_id)
+        comp_node.setAttribute('name', comp_name)
+        self._components_node.appendChild(comp_node)
+        
+        comp = Component(self, comp_node)
+        comp.parse_timelines()
+        
+        self._components.append(comp)
+        self._comp_names.add(comp_name)
+        pass
+
+    def add_component_node(self, comp_node):
+        comp = Component(self, comp_node)
+        comp_name = comp.name()
+        if self.has_component(comp_name):
+            raise ValueError, \
+                'the name of a ns0:component is duplicated'
+
+        self._components.append(comp)
+        self._comp_names.add(comp_name)
+        pass
+
+    def rm_component(self, comp_name):
+        if not self.has_component(comp_name):
+            raise ValueError, 'try to remove a non-existed component'
+
+        self._comp_names.remove(comp_name)
+        for i, comp in enumerate(self._components):
+            if comp.name() == comp_name:
+                del self._components[i]
+                self._comp_names.remove(comp_name)
+                break
+            pass
+        pass
+
+    def switch_timeline(self, timeline_name):
+        tl = self._cur_comp.get_timeline(timeline_name)
+        self._cur_timeline = tl
+        self._scenes_node = tl.scenes_node # of class domview
+
+        self._monitor_rescan()  # from domview_monitor
+        pass
+
+    def add_timeline(self, timeline_name):
+        self._cur_comp.add_timeline(timeline_name)
+        pass
+
+    def rm_timeline(self, timeline_name):
+        self._cur_comp.rm_timeline(timeline_name)
+        pass
+    pass
+
+
 ## \brief Monitor changes of DOM-tree.
 #
 # This class monitors DOM-tree to maintain _maxframe and maps for node ID to
@@ -35,6 +275,17 @@
                                    self._on_attr_modified, None)
 	pass
 
+    ## \brief Rescan the tree.
+    #
+    def _monitor_rescan(self):
+        self._maxframe = 0
+        self._id2node = {}
+        self._group2scene = {}
+
+        self._collect_node_ids()
+        self._collect_all_scenes()
+        pass
+
     def _on_insert_node(self, node, child):
 	for cchild in child.childList():
 	    self._on_insert_node(child, cchild)
@@ -336,6 +587,17 @@
 	    node.appendChild(scenes_node)
 	    self._scenes_node = scenes_node
 	    pass
+        
+	for n in node.childList():
+	    if n.name() == 'ns0:components':
+		self._components_node = n
+		break
+	    pass
+	else:
+	    components_node = self._doc.createElement("ns0:components")
+	    node.appendChild(components_node)
+	    self._components_node = components_node
+	    pass
 	pass
 
     def _parse_all_layers(self):