changeset 1253:07e0cb1e051d

Add class consistency_checker for domview_ui. - consistency_checker is to check consistency of the DOM-tree associated with a domview_ui. - It is so closed to domview_ui, so it may access private variables. - But, it uses public interface of domview_ui if possible. - consistency_checker is not integrated to domview_ui for separating functions of consistency checking from the domview_ui. It collects relative logic into a place and setups a boundary from others.
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 11 Jan 2011 11:43:32 +0800
parents 71222a6b4c06
children 0cb5979549be
files pyink/MBScene.py pyink/consistency.py pyink/data_monitor.py pyink/dom_event.py pyink/domview.py pyink/domview_ui.py
diffstat 6 files changed, 159 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/MBScene.py	Tue Jan 11 10:36:39 2011 +0800
+++ b/pyink/MBScene.py	Tue Jan 11 11:43:32 2011 +0800
@@ -8,6 +8,7 @@
 import pybInkscape
 from tween import scenes_director
 from domview_ui import domview_ui
+from data_monitor import data_monitor
 
 # Please refer to
 # http://www.assembla.com/wiki/show/MadButterfly/Inkscape_extention
@@ -37,63 +38,6 @@
 #       scene into two scenes with the same content.
 #
 
-## \brief Monitor accessing on the dta model.
-#
-# This class is a meta-class that monitor data accessing for its instance
-# classes.
-#
-# All methods, of instance classes, who's name is prefixed with 'do' are
-# monitored.  When a monitored method was called, monitor will try to lock
-# _domview of the object.  The method is only called if successfully acquiring
-# the lock, or return immediately.  The lock is released after the calling
-# returned.
-#
-class data_monitor(type):
-    def __new__(mclazz, name, bases, clazz_dict):
-	import os
-
-	debug_level = 0
-	if os.environ.has_key('DATA_MONITOR_DBG'):
-	    debug_level = int(os.environ['DATA_MONITOR_DBG'])
-	    pass
-	
-	def gen_sentinel(name, func):
-	    def sentinel(self, *args, **kws):
-		if debug_level >= 1:
-		    print 'calling %s' % (name)
-		    pass
-		if debug_level >= 2:
-		    print '    args: %s' % (repr(args))
-		    print '    kws:  %s' % (repr(kws))
-		    pass
-		
-		if not self._domview.lock(): # can not lock
-		    if debug_level >= 1:
-			print '  fault to lock'
-			pass
-		    return
-		
-		try:
-		    func(self, *args, **kws)
-		finally:
-		    self._domview.unlock()
-		    pass
-		pass
-	    return sentinel
-
-	for attr_name in clazz_dict:
-	    if (not attr_name.startswith('do')) or \
-		    (not callable(clazz_dict[attr_name])):
-		continue
-	    clazz_dict[attr_name] = \
-		gen_sentinel(attr_name, clazz_dict[attr_name])
-	    pass
-	
-	clazz = type.__new__(mclazz, name, bases, clazz_dict)
-	
-	return clazz
-    pass
-
 ## \brief MBScene connect GUI and DOM-tree
 #
 # This method accepts user actions and involves domview_ui to update
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyink/consistency.py	Tue Jan 11 11:43:32 2011 +0800
@@ -0,0 +1,62 @@
+import dom_event
+from data_monitor import data_monitor
+
+## \brief Check consistency of a DOM-tree associated with a domview_ui.
+#
+# This is a co-worker of \ref domview_ui to check DOM-tree and make
+# sure consistency of scenes, scene groups in the DOM-tree.  It also
+# updates layer list of \ref domview_ui to reflect last changes of the
+# DOM-tree.
+#
+# Since it is a consistency checker, it must well understanding
+# structure that expected by domview_ui.  So, this class is highly
+# closed to the internal of \ref domview_ui.  It is separated from
+# domview_ui for collecting related logic and functions in a place to
+# set up a clear boundary from the functions provided by \ref
+# domview_ui.
+#
+# This class is expected to access private variables of \ref
+# domview_ui.  But, use public interface of domview_ui if possible.
+#
+# This class is also monitored by \ref data_monitor to monitor the
+# accessing to domview_ui.
+#
+class consistency_checker(object):
+    __metaclass__ = data_monitor
+    
+    def __init__(self, domview_ui):
+        self._domview = domview_ui
+        self._doc = None
+        self._root = None
+        pass
+
+    def _start_check(self):
+        doc = self._doc
+	dom_event.addEventListener(doc, 'DOMNodeInserted',
+                                   self.do_insert_node, None)
+	dom_event.addEventListener(doc, 'DOMNodeRemoved',
+                                   self.do_remove_node, None)
+	dom_event.addEventListener(doc, 'DOMAttrModified',
+                                   self.do_attr_modified, None)
+        pass
+    
+    ## \brief Handle a new document.
+    #
+    # This method is called by domview_ui.handle_doc_root().
+    #
+    def handle_doc_root(self, doc, root):
+        self._doc = doc
+        self._root = root
+
+        self._start_check()
+        pass
+
+    def do_insert_node(self, node, child):
+        pass
+
+    def do_remove_node(self, node, child):
+        pass
+
+    def do_attr_modified(self, node, name, old_value, new_value):
+        pass
+    pass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyink/data_monitor.py	Tue Jan 11 11:43:32 2011 +0800
@@ -0,0 +1,57 @@
+import os
+
+## \brief Monitor accessing on the dta model.
+#
+# This class is a meta-class that monitor data accessing for its instance
+# classes.
+#
+# All methods, of instance classes, who's name is prefixed with 'do' are
+# monitored.  When a monitored method was called, monitor will try to lock
+# _domview of the object.  The method is only called if successfully acquiring
+# the lock, or return immediately.  The lock is released after the calling
+# returned.
+#
+class data_monitor(type):
+    def __new__(mclazz, name, bases, clazz_dict):
+	debug_level = 0
+	if os.environ.has_key('DATA_MONITOR_DBG'):
+	    debug_level = int(os.environ['DATA_MONITOR_DBG'])
+	    pass
+	
+	def gen_sentinel(func_name, func):
+	    def sentinel(self, *args, **kws):
+		if debug_level >= 1:
+		    print 'calling %s.%s' % (name, func_name)
+		    pass
+		if debug_level >= 2:
+		    print '    args: %s' % (repr(args))
+		    print '    kws:  %s' % (repr(kws))
+		    pass
+		
+		if not self._domview.lock(): # can not lock
+		    if debug_level >= 1:
+			print '  fault to lock'
+			pass
+		    return
+		
+		try:
+		    func(self, *args, **kws)
+		finally:
+		    self._domview.unlock()
+		    pass
+		pass
+	    return sentinel
+
+	for attr_name in clazz_dict:
+	    if (not attr_name.startswith('do')) or \
+		    (not callable(clazz_dict[attr_name])):
+		continue
+	    clazz_dict[attr_name] = \
+		gen_sentinel(attr_name, clazz_dict[attr_name])
+	    pass
+	
+	clazz = type.__new__(mclazz, name, bases, clazz_dict)
+	
+	return clazz
+    pass
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyink/dom_event.py	Tue Jan 11 11:43:32 2011 +0800
@@ -0,0 +1,29 @@
+import pybInkscape
+
+class ObjectWatcher(pybInkscape.PYNodeObserver):
+    def __init__(self, obj, type, func, arg):
+        self.obj = obj
+	self.type = type
+	self.func = func
+	self.arg = arg
+
+    def notifyChildAdded(self, node, child, prev):
+        if self.type == 'DOMNodeInserted':
+	    self.func(node, child)
+    def notifyChildRemoved(self, node, child, prev):
+        if self.type == 'DOMNodeRemoved':
+	    self.func(node, child)
+    def notifyChildOrderChanged(self,node,child,prev):
+        pass
+    def notifyContentChanged(self,node,old_content,new_content):
+        if self.type == 'DOMSubtreeModified':
+	    self.func(node)
+    def notifyAttributeChanged(self,node, name, old_value, new_value):
+        if self.type == 'DOMAttrModified':
+	    self.func(node, name, old_value, new_value)
+
+def addEventListener(obj, type, func, arg):
+    obs = ObjectWatcher(obj, type, func, arg)
+    obj.addSubtreeObserver(obs)
+    pass
+
--- a/pyink/domview.py	Tue Jan 11 10:36:39 2011 +0800
+++ b/pyink/domview.py	Tue Jan 11 11:43:32 2011 +0800
@@ -1,5 +1,5 @@
 import random
-import pybInkscape
+import dom_event
 from tween import TweenObject
 
 class Layer:
@@ -9,34 +9,6 @@
 	pass
     pass
 
-class ObjectWatcher(pybInkscape.PYNodeObserver):
-    def __init__(self, obj, type, func, arg):
-        self.obj = obj
-	self.type = type
-	self.func = func
-	self.arg = arg
-
-    def notifyChildAdded(self, node, child, prev):
-        if self.type == 'DOMNodeInserted':
-	    self.func(node, child)
-    def notifyChildRemoved(self, node, child, prev):
-        if self.type == 'DOMNodeRemoved':
-	    self.func(node, child)
-    def notifyChildOrderChanged(self,node,child,prev):
-        pass
-    def notifyContentChanged(self,node,old_content,new_content):
-        if self.type == 'DOMSubtreeModified':
-	    self.func(node)
-    def notifyAttributeChanged(self,node, name, old_value, new_value):
-        if self.type == 'DOMAttrModified':
-	    self.func(node, name, old_value, new_value)
-
-def addEventListener(obj, type, func, arg):
-    obs = ObjectWatcher(obj, type, func, arg)
-    obj.addSubtreeObserver(obs)
-    pass
-
-
 ## \brief Monitor changes of DOM-tree.
 #
 # This class monitors DOM-tree to maintain _maxframe and maps for node ID to
@@ -55,9 +27,12 @@
 	self._collect_all_scenes()
 	
 	doc = self._doc
-	addEventListener(doc, 'DOMNodeInserted', self._on_insert_node, None)
-	addEventListener(doc, 'DOMNodeRemoved', self._on_remove_node, None)
-	addEventListener(doc, 'DOMAttrModified', self._on_attr_modified, None)
+	dom_event.addEventListener(doc, 'DOMNodeInserted',
+                                   self._on_insert_node, None)
+	dom_event.addEventListener(doc, 'DOMNodeRemoved',
+                                   self._on_remove_node, None)
+	dom_event.addEventListener(doc, 'DOMAttrModified',
+                                   self._on_attr_modified, None)
 	pass
 
     def _on_insert_node(self, node, child):
--- a/pyink/domview_ui.py	Tue Jan 11 10:36:39 2011 +0800
+++ b/pyink/domview_ui.py	Tue Jan 11 11:43:32 2011 +0800
@@ -2,7 +2,7 @@
 from tween import TweenObject
 from frameline import frameline, frameruler
 from domview import domview
-
+import consistency
 
 ## \brief Maintain a stack of frameline UI component.
 #
@@ -361,6 +361,7 @@
 	self._dom = domview()
         self._doc = None
         self._root = None
+        self._consistency_checker = consistency.consistency_checker(self)
         self._lock = False
 	pass
 
@@ -409,6 +410,7 @@
 
         self._doc = doc
         self._root = root
+        self._consistency_checker.handle_doc_root(doc, root)
 	pass
 
     ## \brief Mark given frame as a key frame.