# HG changeset patch # User Thinker K.F. Li # Date 1294717412 -28800 # Node ID 07e0cb1e051d45e8569dc2e54c2a15135da244cf # Parent 71222a6b4c063cc4b0471c1e7412aebb621f964a 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. diff -r 71222a6b4c06 -r 07e0cb1e051d pyink/MBScene.py --- 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 diff -r 71222a6b4c06 -r 07e0cb1e051d pyink/consistency.py --- /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 diff -r 71222a6b4c06 -r 07e0cb1e051d pyink/data_monitor.py --- /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 + diff -r 71222a6b4c06 -r 07e0cb1e051d pyink/dom_event.py --- /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 + diff -r 71222a6b4c06 -r 07e0cb1e051d pyink/domview.py --- 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): diff -r 71222a6b4c06 -r 07e0cb1e051d pyink/domview_ui.py --- 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.