changeset 1299:6949e2b6cae2

Add unlink clone checker. - Monitor changes of DOM-tree of the document - Unlinking a clone is actually removing the clone and copying nodes from the source. - Copy value of ID of a node to saved_id to track source of copy nodes. - For a new node with 'saved_id' is a copy of another node. - Copy vulae of 'saved_id' to 'ns0:duplicate-src' to keep the source - Change value of 'saved_id' to the value of ID of the node for later copying. - For a new node without 'saved_id' is not a copy of another node. - only set 'saved_id' to the value of its ID.
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 16 Jan 2011 16:13:37 +0800
parents 2a5da457474d
children 2a35a1cb6cdf
files pyink/domview.py pyink/domview_ui.py pyink/unlink_clone.py
diffstat 3 files changed, 113 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/domview.py	Sun Jan 16 11:04:29 2011 +0800
+++ b/pyink/domview.py	Sun Jan 16 16:13:37 2011 +0800
@@ -484,6 +484,7 @@
 	gid = self.new_id()
 	scene_group.setAttribute("id", gid)
 	scene_group.setAttribute("inkscape:groupmode", "layer")
+        scene_group.setAttribute('scene_group', 'true')
 
 	layer.group.appendChild(scene_group)
 	
--- a/pyink/domview_ui.py	Sun Jan 16 11:04:29 2011 +0800
+++ b/pyink/domview_ui.py	Sun Jan 16 16:13:37 2011 +0800
@@ -3,6 +3,7 @@
 from frameline import frameline, frameruler
 from domview import domview
 import consistency
+import unlink_clone
 
 ## \brief Maintain a stack of frameline UI component.
 #
@@ -823,12 +824,14 @@
         super(domview_ui_with_workers, self).__init__()
         
         self._consistency_checker = consistency.consistency_checker(self)
+        self._unlink_clone_checker = unlink_clone.unlink_clone_checker(self)
         pass
 
     def handle_doc_root(self, doc, root):
         super(domview_ui_with_workers, self).handle_doc_root(doc, root)
         
         self._consistency_checker.handle_doc_root(doc, root)
+        self._unlink_clone_checker.handle_doc_root(doc, root)
         pass
     pass
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyink/unlink_clone.py	Sun Jan 16 16:13:37 2011 +0800
@@ -0,0 +1,109 @@
+import dom_event
+from data_monitor import data_monitor
+
+class unlink_clone_checker(object):
+    __metaclass__ = data_monitor
+    
+    _no_change_attrs = ('ns0:duplicate-src', 'saved_id')
+    
+    def __init__(self, domview_ui):
+        self._domviewui = domview_ui
+        self._locker = 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, 'DOMAttrModified',
+                                   self.do_attr_modified, None)
+        pass
+
+    def handle_doc_root(self, doc, root):
+        self._doc = doc
+        self._root = root
+
+        self._start_check()
+        pass
+
+    def _handle_unlinked_or_copied_nodes(self, node, child):
+        try:
+            saved_id = child.getAttribute('saved_id')
+        except:                 # Skip it for losting saved_id
+            pass
+        else:
+            child.setAttribute('ns0:duplicate-src', saved_id)
+            pass
+        
+        try:
+            child_id = child.getAttribute('id')
+        except:                 # still have no ID.
+            pass                # Assign saved_id later with attr
+                                # modified event.
+        else:
+            child.setAttribute('saved_id', child_id)
+            pass
+        pass
+
+    def _handle_new_nodes(self, node, child):
+        if child.name() == 'svg:use':
+            return
+
+        try:
+            child_id = child.getAttribute('id')
+        except KeyError:
+            return
+        child.setAttribute('saved_id', child_id)
+        pass
+
+    ## \brief Check inserted node recurisvely.
+    #
+    # Travel the tree in post-order.
+    #
+    def _handle_insert_node_recursive(self, node, child):
+        #
+        # Traveling forest of children.
+        #
+        for cchild in child.childList():
+            self._handle_insert_node_recursive(child, cchild)
+            pass
+        
+        #
+        # Visit the node
+        #
+        try:
+            child_id = child.getAttribute('saved_id')
+        except KeyError:                 # have no saved_id
+            pass
+        else:
+            self._handle_unlinked_or_copied_nodes(node, child)
+            return
+
+        # have no saved_id
+        self._handle_new_nodes(node, child)
+        pass
+
+    def do_insert_node(self, node, child):
+        self._handle_insert_node_recursive(node, child)
+        pass
+
+    def do_attr_modified(self, node, name, old_value, new_value):
+        if name == 'id' and node.name() != 'svg:use':
+            #
+            # The ID of a node may not be assigned when it being
+            # inserted, and be assigned later.  So, we checking
+            # attribute modification event to assign value of
+            # saved_id.
+            #
+            node.setAttribute('saved_id', new_value)
+        elif old_value and (name in self._no_change_attrs):
+            #
+            # Restore to old value for attributes that is not allowed
+            # to be changed by the user.
+            #
+            node.setAttribute(name, old_value)
+            pass
+        pass
+    pass