Mercurial > MadButterfly
diff pyink/unlink_clone.py @ 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 | |
children | 2a35a1cb6cdf |
line wrap: on
line diff
--- /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