Mercurial > MadButterfly
comparison pyink/MBScene.py @ 1191:6442fb198418
Refactory insertKeyScene() and fix bug of ObjectWatcher
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Sun, 02 Jan 2011 13:53:38 +0800 |
parents | a4df892fb4e5 |
children | 79a3f82edaac |
comparison
equal
deleted
inserted
replaced
1190:a4df892fb4e5 | 1191:6442fb198418 |
---|---|
70 self.obj = obj | 70 self.obj = obj |
71 self.type = type | 71 self.type = type |
72 self.func = func | 72 self.func = func |
73 self.arg = arg | 73 self.arg = arg |
74 | 74 |
75 def notifyChildAdded(self,node,child,prev): | 75 def notifyChildAdded(self, node, child, prev): |
76 if self.type == 'DOMNodeInserted': | 76 if self.type == 'DOMNodeInserted': |
77 self.func(node) | 77 self.func(node, child) |
78 def notifyChildRemoved(self,node,child,prev): | 78 def notifyChildRemoved(self, node, child, prev): |
79 if self.type == 'DOMNodeRemoved': | 79 if self.type == 'DOMNodeRemoved': |
80 self.func(node) | 80 self.func(node, child) |
81 def notifyChildOrderChanged(self,node,child,prev): | 81 def notifyChildOrderChanged(self,node,child,prev): |
82 pass | 82 pass |
83 def notifyContentChanged(self,node,old_content,new_content): | 83 def notifyContentChanged(self,node,old_content,new_content): |
84 if self.type == 'DOMSubtreeModified': | 84 if self.type == 'DOMSubtreeModified': |
85 self.func(node) | 85 self.func(node) |
86 def notifyAttributeChanged(self,node, name, old_value, new_value): | 86 def notifyAttributeChanged(self,node, name, old_value, new_value): |
87 # print 'attr',node,name,old_value,new_value | |
88 if self.type == 'DOMAttrModified': | 87 if self.type == 'DOMAttrModified': |
89 self.func(node, name, old_value, new_value) | 88 self.func(node, name, old_value, new_value) |
90 | 89 |
91 def addEventListener(obj, type, func,arg): | 90 def addEventListener(obj, type, func,arg): |
92 obs = ObjectWatcher(obj,type,func,arg) | 91 obs = ObjectWatcher(obj,type,func,arg) |
170 addEventListener(doc,'DOMNodeInserted', self._on_insert_node, None) | 169 addEventListener(doc,'DOMNodeInserted', self._on_insert_node, None) |
171 addEventListener(doc,'DOMNodeRemoved', self._on_remove_node, None) | 170 addEventListener(doc,'DOMNodeRemoved', self._on_remove_node, None) |
172 addEventListener(doc, 'DOMAttrModified', self._on_attr_modified, None) | 171 addEventListener(doc, 'DOMAttrModified', self._on_attr_modified, None) |
173 pass | 172 pass |
174 | 173 |
175 def _on_insert_node(self, node): | 174 def _on_insert_node(self, node, child): |
176 try: | 175 try: |
177 node_id = node.getAttribute('id') | 176 child_id = child.getAttribute('id') |
178 except: | 177 except: |
179 pass | 178 pass |
180 else: | 179 else: |
181 if node_id not in self._id2node: | 180 if child_id not in self._id2node: |
182 self._id2node[node_id] = node | 181 self._id2node[child_id] = child |
183 pass | 182 pass |
184 pass | 183 pass |
185 | 184 |
186 if node.name() == 'ns0:scene': | 185 if child.name() == 'ns0:scene': |
187 try: | 186 try: |
188 ref = node.getAttribute('ref') | 187 ref = child.getAttribute('ref') |
189 except: | 188 except: |
190 pass | 189 pass |
191 else: | 190 else: |
192 print 'scene %s' % (ref) | |
193 if ref not in self._group2scene: | 191 if ref not in self._group2scene: |
194 self._group2scene[ref] = node | 192 self._group2scene[ref] = child |
195 pass | 193 pass |
196 pass | 194 pass |
197 pass | 195 pass |
198 pass | 196 pass |
199 | 197 |
200 def _on_remove_node(self, node): | 198 def _on_remove_node(self, node, child): |
201 try: | 199 try: |
202 node_id = node.getAttribute('id') | 200 child_id = child.getAttribute('id') |
203 except: | 201 except: |
204 pass | 202 pass |
205 else: | 203 else: |
206 if node_id not in self._id2node: | 204 if child_id not in self._id2node: |
207 raise ValueError, \ | 205 raise ValueError, \ |
208 'remove a node that is never known (%s)' % (node_id) | 206 'remove a node that is never known (%s)' % (child_id) |
209 del self._id2node[node_id] | 207 del self._id2node[child_id] |
210 pass | 208 pass |
211 | 209 |
212 if node.name() == 'ns0:scene': | 210 if child.name() == 'ns0:scene': |
213 try: | 211 try: |
214 ref = node.getAttribute('ref') | 212 ref = child.getAttribute('ref') |
215 except: | 213 except: |
216 pass | 214 pass |
217 else: | 215 else: |
218 del self._group2scene[ref] | 216 del self._group2scene[ref] |
219 pass | 217 pass |
220 pass | 218 pass |
221 pass | 219 pass |
222 | 220 |
223 def _on_attr_modified(self, node, name, old_value, new_value): | 221 def _on_attr_modified(self, node, name, old_value, new_value): |
224 print 'chg attr %s' % (name) | |
225 if name == 'id' and old_value != new_value: | 222 if name == 'id' and old_value != new_value: |
226 if old_value and (old_value not in self._id2node): | 223 if old_value and (old_value not in self._id2node): |
227 raise ValueError, \ | 224 raise ValueError, \ |
228 'old ID value of passed node is valid one (%s)' % \ | 225 'old ID value of passed node is valid one (%s)' % \ |
229 (old_value) | 226 (old_value) |
236 del self._id2node[old_value] | 233 del self._id2node[old_value] |
237 pass | 234 pass |
238 self._id2node[new_value] = node | 235 self._id2node[new_value] = node |
239 pass | 236 pass |
240 elif name == 'ref' and node.name() == 'ns0:scene': | 237 elif name == 'ref' and node.name() == 'ns0:scene': |
241 print 'change ref %s' % (new_value) | |
242 if old_value == new_value: | 238 if old_value == new_value: |
243 return | 239 return |
244 if old_value: | 240 if old_value: |
245 node = self._group2scene[old_value] # use old node. Binding | 241 node = self._group2scene[old_value] # use old node. Binding |
246 # may generate a new | 242 # may generate a new |
275 | 271 |
276 def get_node(self, node_id): | 272 def get_node(self, node_id): |
277 return self._id2node[node_id] | 273 return self._id2node[node_id] |
278 | 274 |
279 def get_scene(self, group_id): | 275 def get_scene(self, group_id): |
280 print 'get_scene %s' % (group_id) | |
281 return self._group2scene[group_id] | 276 return self._group2scene[group_id] |
282 | 277 |
283 def new_id(self): | 278 def new_id(self): |
284 while True: | 279 while True: |
285 candidate = 's%d' % int(random.random()*100000) | 280 candidate = 's%d' % int(random.random()*100000) |
291 | 286 |
292 | 287 |
293 ## \brief Layer of MBScene to manipulate DOM tree. | 288 ## \brief Layer of MBScene to manipulate DOM tree. |
294 # | 289 # |
295 class MBScene_dom(MBScene_dom_monitor): | 290 class MBScene_dom(MBScene_dom_monitor): |
291 # Declare variables, here, for keeping tracking | |
292 _doc = None | |
293 _root = None | |
294 _scenes_group = None | |
295 | |
296 def __init__(self, *args, **kws): | 296 def __init__(self, *args, **kws): |
297 super(MBScene_dom, self).__init__() | 297 super(MBScene_dom, self).__init__() |
298 pass | 298 pass |
299 | 299 |
300 def handle_doc_root(self, doc, root): | 300 def handle_doc_root(self, doc, root): |
380 raise RuntimeError, \ | 380 raise RuntimeError, \ |
381 'can not find <svg:metadata> node in the document' | 381 'can not find <svg:metadata> node in the document' |
382 | 382 |
383 for n in node.childList(): | 383 for n in node.childList(): |
384 if n.name() == 'ns0:scenes': | 384 if n.name() == 'ns0:scenes': |
385 self._scenes_node = n | |
385 break | 386 break |
386 pass | 387 pass |
387 else: | 388 else: |
388 ns = "http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" | 389 ns = "http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" |
389 self._root.setAttribute("xmlns:ns0", ns) | 390 self._root.setAttribute("xmlns:ns0", ns) |
390 scenes_node = self._doc.createElement("ns0:scenes") | 391 scenes_node = self._doc.createElement("ns0:scenes") |
391 node.appendChild(scenes_node) | 392 node.appendChild(scenes_node) |
392 pass | 393 self._scenes_node = scenes_node |
393 pass | 394 pass |
394 | 395 pass |
396 | |
397 ## \brief Create and add a ns0:scene node under ns0:scenes subtree. | |
398 # | |
399 def _add_scene_node(self, start, end, | |
400 frame_type=TweenObject.TWEEN_TYPE_NORMAL, | |
401 ref=None): | |
402 type_names = ('normal', 'scale') | |
403 scenes_node = self._scenes_node | |
404 doc = self._doc | |
405 | |
406 scene_node = doc.createElement('ns0:scene') | |
407 scene_node.setAttribute('start', str(start)) | |
408 if start != end: | |
409 scene_node.setAttribute('end', str(end)) | |
410 pass | |
411 type_name = type_names[frame_type] | |
412 scene_node.setAttribute('type', type_name) | |
413 if ref: | |
414 scene_node.setAttribute('ref', ref) | |
415 pass | |
416 | |
417 scenes_node.appendChild(scene_node) | |
418 | |
419 return scene_node | |
420 | |
421 ## \brief Create and add a svg:g for a scene under a group for a layer. | |
422 # | |
423 def _add_scene_group(self, layer_idx): | |
424 layer = self.layers[layer_idx] | |
425 doc = self._doc | |
426 | |
427 scene_group = doc.createElement('svg:g') | |
428 gid = self.new_id() | |
429 scene_group.setAttribute("id", gid) | |
430 scene_group.setAttribute("inkscape:groupmode", "layer") | |
431 | |
432 layer.group.appendChild(scene_group) | |
433 | |
434 return scene_group | |
435 | |
395 def insertKeyScene(self, line, frame): | 436 def insertKeyScene(self, line, frame): |
396 """ | 437 """ |
397 Insert a new key scene into the stage. If the nth is always a | 438 Insert a new key scene into the stage. If the nth is always a |
398 key scene, we will return without changing anything. If the | 439 key scene, we will return without changing anything. If the |
399 nth is a filled scene, we will break the original scene into | 440 nth is a filled scene, we will break the original scene into |
400 two parts. If the nth is out of any scene, we will append a | 441 two parts. If the nth is out of any scene, we will append a |
401 new scene. | 442 new scene. |
402 | 443 |
403 """ | 444 """ |
404 rdoc = self._doc | 445 doc = self._doc |
405 scene_group = rdoc.createElement("svg:g") | 446 layer_idx = self._framelines.index(line) |
406 found = False | 447 |
407 for node in line.layer_group.childList(): | 448 scene_group = self._add_scene_group(layer_idx) |
449 scene_group_id = scene_group.getAttribute('id') | |
450 scene_node = self._add_scene_node(frame, frame, ref=scene_group_id) | |
451 line.add_keyframe(frame, scene_node) | |
452 | |
453 for node in self.layers[layer_idx].group.childList(): | |
408 try: | 454 try: |
409 label = node.getAttribute("inkscape:label") | 455 label = node.getAttribute('inkscape:label') |
410 except: | 456 except: |
411 continue | 457 continue |
412 if label == "dup": | 458 if label == 'dup': |
413 #FIXME: The duplication here is not perfect. We should | 459 node.setAttribute('style', 'display: none') |
414 # get the element inside the group and apply the | 460 pass |
415 # transformation matrix to it directly. | 461 pass |
416 for n in node.childList(): | 462 pass |
417 scene_group.appendChild(n.duplicate(self._doc)) | 463 |
418 found = True | |
419 node.setAttribute("style","display:none") | |
420 break | |
421 pass | |
422 pass | |
423 | |
424 if found == False: | |
425 txt = rdoc.createElement("svg:rect") | |
426 txt.setAttribute("x","0") | |
427 txt.setAttribute("y","0") | |
428 txt.setAttribute("width","100") | |
429 txt.setAttribute("height","100") | |
430 txt.setAttribute("style","fill:#ff00") | |
431 scene_group.appendChild(txt) | |
432 | |
433 gid = line.layer_group.getAttribute('inkscape:label')+self.new_id() | |
434 scene_group.setAttribute("id",gid) | |
435 scene_group.setAttribute("inkscape:groupmode","layer") | |
436 line.layer_group.appendChild(scene_group) | |
437 line.add_keyframe(frame, scene_group) | |
438 self.update_scenes_of_dom() | |
439 pass | |
440 | |
441 def add_scene_on_dom(self, frameline, scenes_node): | 464 def add_scene_on_dom(self, frameline, scenes_node): |
442 doc = self._doc | 465 doc = self._doc |
443 for start_idx, stop_idx, tween_type in frameline.get_frame_blocks(): | 466 for start_idx, stop_idx, tween_type in frameline.get_frame_blocks(): |
444 scene_node = frameline.get_frame_data(start_idx) | 467 scene_node = frameline.get_frame_data(start_idx) |
445 tween_type_idx = self._frameline_tween_types.index(tween_type) | 468 tween_type_idx = self._frameline_tween_types.index(tween_type) |
786 pass | 809 pass |
787 pass | 810 pass |
788 pass | 811 pass |
789 pass | 812 pass |
790 | 813 |
791 def enterGroup(self,obj): | 814 def enterGroup(self, obj): |
792 for l in self.layers: | 815 for l in self.layers: |
793 for s in l.group.childList(): | 816 for s in l.group.childList(): |
794 if s.getAttribute('id') == obj.getAttribute("id"): | 817 if s.getAttribute('id') == obj.getAttribute("id"): |
795 self.desktop.setCurrentLayer(s.spitem) | 818 self.desktop.setCurrentLayer(s.spitem) |
796 pass | 819 pass |
803 start, stop, tween_type = frameline.get_frame_block(frame_idx) | 826 start, stop, tween_type = frameline.get_frame_block(frame_idx) |
804 except: | 827 except: |
805 return | 828 return |
806 | 829 |
807 scene_node = frameline.get_frame_data(start) | 830 scene_node = frameline.get_frame_data(start) |
808 self.enterGroup(scene_node) | 831 scene_group_id = scene_node.getAttribute('ref') |
832 scene_group = self.get_node(scene_group_id) | |
833 self.enterGroup(scene_group) | |
809 self.setTweenType(tween_type) | 834 self.setTweenType(tween_type) |
810 pass | 835 pass |
811 | 836 |
812 def setTweenType(self, tween_type): | 837 def setTweenType(self, tween_type): |
813 sel_type = MBScene._frameline_tween_types.index(tween_type) | 838 sel_type = MBScene._frameline_tween_types.index(tween_type) |
896 line.connect('motion-notify-event', self._remove_active_frame) | 921 line.connect('motion-notify-event', self._remove_active_frame) |
897 pass | 922 pass |
898 vbox.show_all() | 923 vbox.show_all() |
899 pass | 924 pass |
900 | 925 |
901 ## \brief Update conetent of frameliens according layers. | 926 ## \brief Update conetent of framelines according layers. |
902 # | 927 # |
903 def _update_framelines(self): | 928 def _update_framelines(self): |
904 for frameline in self._framelines: | 929 for frameline in self._framelines: |
905 layer = frameline.layer | 930 layer = frameline.layer |
906 if frameline.layer_group.getAttribute("inkscape:label")==None: | 931 if frameline.layer_group.getAttribute("inkscape:label")==None: |
1153 def onOK(self,event): | 1178 def onOK(self,event): |
1154 self.OK = True | 1179 self.OK = True |
1155 gtk.main_quit() | 1180 gtk.main_quit() |
1156 pass | 1181 pass |
1157 | 1182 |
1158 def updateUI(self,node=None,arg=None): | 1183 def updateUI(self, node=None, child=None, arg=None): |
1159 if self._lockui: return | 1184 if self._lockui: return |
1160 | 1185 |
1161 if self.last_update!= None: | 1186 if self.last_update!= None: |
1162 glib.source_remove(self.last_update) | 1187 glib.source_remove(self.last_update) |
1163 self.last_update = glib.timeout_add(300,self._updateUI) | 1188 self.last_update = glib.timeout_add(300,self._updateUI) |