comparison pyink/MBScene.py @ 1188:45e3a9273af2

Move code about monitoring DOM-tree to MBScene_dom_monitor
author Thinker K.F. Li <thinker@codemud.net>
date Fri, 31 Dec 2010 21:40:35 +0800
parents 9d784a987d87
children 9cf183faf89f
comparison
equal deleted inserted replaced
1185:9d784a987d87 1188:45e3a9273af2
85 if self.type == 'DOMSubtreeModified': 85 if self.type == 'DOMSubtreeModified':
86 self.func(node) 86 self.func(node)
87 def notifyAttributeChanged(self,node, name, old_value, new_value): 87 def notifyAttributeChanged(self,node, name, old_value, new_value):
88 # print 'attr',node,name,old_value,new_value 88 # print 'attr',node,name,old_value,new_value
89 if self.type == 'DOMAttrModified': 89 if self.type == 'DOMAttrModified':
90 self.func(node,name) 90 self.func(node, name, old_value, new_value)
91 91
92 def addEventListener(obj, type, func,arg): 92 def addEventListener(obj, type, func,arg):
93 obs = ObjectWatcher(obj,type,func,arg) 93 obs = ObjectWatcher(obj,type,func,arg)
94 obj.addSubtreeObserver(obs) 94 obj.addSubtreeObserver(obs)
95 95
151 pass 151 pass
152 yield node 152 yield node
153 pass 153 pass
154 pass 154 pass
155 155
156
157 ## \brief Monitor changes of DOM-tree.
158 #
159 class MBScene_dom_monitor(object):
160 def __init__(self, *args, **kws):
161 super(MBScene_dom_monitor, self).__init__()
162
163 self._id2node = {} # map ID to the node in the DOM tree.
164 pass
165
166 def _start_monitor(self):
167 self._collect_node_ids()
168
169 doc = self._doc
170 addEventListener(doc,'DOMNodeInserted', self._on_insert_node, None)
171 addEventListener(doc,'DOMNodeRemoved', self._on_remove_node, None)
172 addEventListener(doc, 'DOMAttrModified', self._on_attr_modified, None)
173 pass
174
175 def _on_insert_node(self, node):
176 try:
177 node_id = node.getAttribute('id')
178 except:
179 return
180 self._id2node[node_id] = node
181 pass
182
183 def _on_remove_node(self, node):
184 try:
185 node_id = node.getAttribute('id')
186 except:
187 return
188 if node_id not in self._id2node:
189 raise ValueError, \
190 'remove a node that is never known (%s)' % (node_id)
191 del self._id2node[node_id]
192 pass
193
194 def _on_attr_modified(self, node, name, old_value, new_value):
195 if name != 'id' or old_value == new_value:
196 return
197
198 if old_value and (old_value not in self._id2node):
199 raise ValueError, \
200 'old ID value of passed node is valid one (%s)' % (old_value)
201 if (new_value in self._id2node):
202 raise ValueError, \
203 'new ID value of passed node is valid one (%s)' % (new_value)
204
205 if old_value:
206 del self._id2node[old_value]
207 pass
208 self._id2node[new_value] = node
209 pass
210
211 def _collect_node_ids(self):
212 self._id2node = {}
213 root = self._root
214 for n in root.childList():
215 self._collect_node_ids_recursive(n)
216 pass
217 pass
218
219 def _collect_node_ids_recursive(self, node):
220 try:
221 node_id = node.getAttribute('id')
222 except:
223 return
224
225 self._id2node[node_id] = node
226 for n in node.childList():
227 self._collect_node_ids_recursive(n)
228 pass
229 pass
230
231 def get_node(self, node_id):
232 return self._id2node[node_id]
233
234 def new_id(self):
235 while True:
236 candidate = 's%d' % int(random.random()*100000)
237 if candidate not in self._id2node:
238 return candidate
239 pass
240 pass
241 pass
242
243
156 ## \brief Layer of MBScene to manipulate DOM tree. 244 ## \brief Layer of MBScene to manipulate DOM tree.
157 # 245 #
158 class MBScene_dom(object): 246 class MBScene_dom(MBScene_dom_monitor):
159 def newID(self): 247 def __init__(self, *args, **kws):
160 while True: 248 super(MBScene_dom, self).__init__()
161 n = 's%d' % int(random.random()*10000) 249 pass
162 #print "try %s" % n 250
163 if self.ID.has_key(n) == False: 251 def handle_doc_root(self, doc, root):
164 return n 252 self._doc = doc
165 pass 253 self._root = root
166 pass 254
167 255 self._start_monitor() # start MBScene_dom_monitor
168 def dumpID(self): 256 pass
169 for a,v in self.ID.items(): 257
170 pass
171 pass
172
173 def dumpattr(self, n): 258 def dumpattr(self, n):
174 s = "" 259 s = ""
175 for a,v in n.attrib.items(): 260 for a,v in n.attrib.items():
176 s = s + ("%s=%s" % (a,v)) 261 s = s + ("%s=%s" % (a,v))
177 pass 262 pass
235 self._parse_one_scenes(n) 320 self._parse_one_scenes(n)
236 break 321 break
237 pass 322 pass
238 else: 323 else:
239 ns = "http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" 324 ns = "http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd"
240 self.root.setAttribute("xmlns:ns0", ns) 325 self._root.setAttribute("xmlns:ns0", ns)
241 scenes = self.document.createElement("ns0:scenes") 326 scenes = self._doc.createElement("ns0:scenes")
242 node.appendChild(scenes) 327 node.appendChild(scenes)
243 pass 328 pass
244 pass 329 pass
245 330
246 def insertKeyScene(self, line, frame): 331 def insertKeyScene(self, line, frame):
250 nth is a filled scene, we will break the original scene into 335 nth is a filled scene, we will break the original scene into
251 two parts. If the nth is out of any scene, we will append a 336 two parts. If the nth is out of any scene, we will append a
252 new scene. 337 new scene.
253 338
254 """ 339 """
255 rdoc = self.document 340 rdoc = self._doc
256 ns = rdoc.createElement("svg:g") 341 ns = rdoc.createElement("svg:g")
257 found = False 342 found = False
258 for node in line.node.childList(): 343 for node in line.node.childList():
259 try: 344 try:
260 label = node.getAttribute("inkscape:label") 345 label = node.getAttribute("inkscape:label")
263 if label == "dup": 348 if label == "dup":
264 #FIXME: The duplication here is not perfect. We should 349 #FIXME: The duplication here is not perfect. We should
265 # get the element inside the group and apply the 350 # get the element inside the group and apply the
266 # transformation matrix to it directly. 351 # transformation matrix to it directly.
267 for n in node.childList(): 352 for n in node.childList():
268 ns.appendChild(n.duplicate(self.document)) 353 ns.appendChild(n.duplicate(self._doc))
269 found = True 354 found = True
270 node.setAttribute("style","display:none") 355 node.setAttribute("style","display:none")
271 break 356 break
272 pass 357 pass
273 pass 358 pass
279 txt.setAttribute("width","100") 364 txt.setAttribute("width","100")
280 txt.setAttribute("height","100") 365 txt.setAttribute("height","100")
281 txt.setAttribute("style","fill:#ff00") 366 txt.setAttribute("style","fill:#ff00")
282 ns.appendChild(txt) 367 ns.appendChild(txt)
283 368
284 gid = line.node.getAttribute('inkscape:label')+self.newID() 369 gid = line.node.getAttribute('inkscape:label')+self.new_id()
285 self.ID[gid]=1
286 ns.setAttribute("id",gid) 370 ns.setAttribute("id",gid)
287 ns.setAttribute("inkscape:groupmode","layer") 371 ns.setAttribute("inkscape:groupmode","layer")
288 line.node.appendChild(ns) 372 line.node.appendChild(ns)
289 line.add_keyframe(frame, ns) 373 line.add_keyframe(frame, ns)
290 self.update_scenes_of_dom() 374 self.update_scenes_of_dom()
291 pass 375 pass
292 376
293 def add_scene_on_dom(self, frameline, scenes_node): 377 def add_scene_on_dom(self, frameline, scenes_node):
294 doc = self.document 378 doc = self._doc
295 for start_idx, stop_idx, tween_type in frameline.get_frame_blocks(): 379 for start_idx, stop_idx, tween_type in frameline.get_frame_blocks():
296 ref = frameline.get_frame_data(start_idx) 380 ref = frameline.get_frame_data(start_idx)
297 tween_type_idx = self._frameline_tween_types.index(tween_type) 381 tween_type_idx = self._frameline_tween_types.index(tween_type)
298 tween_type_name = self._tween_type_names[tween_type_idx] 382 tween_type_name = self._tween_type_names[tween_type_idx]
299 383
307 scene_node.setAttribute("type", tween_type_name) 391 scene_node.setAttribute("type", tween_type_name)
308 pass 392 pass
309 pass 393 pass
310 394
311 def update_scenes_of_dom(self): 395 def update_scenes_of_dom(self):
312 doc = self.root 396 doc = self._root
313 rdoc = self.document 397 rdoc = self._doc
314 for node in doc.childList(): 398 for node in doc.childList():
315 if node.name() == 'svg:metadata': 399 if node.name() == 'svg:metadata':
316 for t in node.childList(): 400 for t in node.childList():
317 if t.name() == "ns0:scenes": 401 if t.name() == "ns0:scenes":
318 node.removeChild(t) 402 node.removeChild(t)
325 pass 409 pass
326 pass 410 pass
327 pass 411 pass
328 pass 412 pass
329 pass 413 pass
414
415 def parseScene(self):
416 """
417 In this function, we will collect all items for the current
418 scene and then relocate them back to the appropriate scene
419 object.
420 """
421 self.layers = []
422 self.scenemap = None
423 doc = self._root
424
425 # TODO: Remove following code sicne this function is for parsing.
426 # Why do this here?
427 addEventListener(doc,'DOMNodeInserted',self.updateUI,None)
428 addEventListener(doc,'DOMNodeRemoved',self.updateUI,None)
429
430 doc.childList()
431 try:
432 self.width = float(doc.getAttribute("width"))
433 self.height= float(doc.getAttribute("height"))
434 except:
435 self.width = 640
436 self.height=480
437 pass
438
439 for node in doc.childList():
440 print node.name()
441 if node.name() == 'svg:metadata':
442 self.parseMetadata(node)
443 pass
444 elif node.name() == 'svg:g':
445 oldscene = None
446 lyobj = Layer(node)
447 self.layers.append(lyobj)
448 lyobj.current_scene = []
449 for scene in node.childList():
450 print scene.getCenter()
451 if scene.name() == 'svg:g':
452 try:
453 label = scene.getAttribute('inkscape:label')
454 if label == 'dup':
455 # TODO: remove this since this functio is for
456 # parsing. Why do this here?
457 node.removeChild(scene)
458 except:
459 pass
460
461 try:
462 scene_id = scene.getAttribute('id')
463 start, stop, tween_type = self.scenemap[scene_id]
464 except:
465 lyobj.current_scene.append(scene)
466 continue
467
468 lyobj.scenes.append(Scene(scene, start, stop,
469 tween_type))
470 pass
471 else:
472 lyobj.current_scene.append(scene)
473 pass
474 pass
475 pass
476 pass
477 pass
478
479 def getLayer(self, layer):
480 for l in self.layers:
481 if l.node.getAttribute('id') == layer:
482 return l
483 pass
484 return None
330 pass 485 pass
331 486
332 class MBScene(MBScene_dom): 487 class MBScene(MBScene_dom):
333 _frameline_tween_types = (frameline.TWEEN_TYPE_NONE, 488 _frameline_tween_types = (frameline.TWEEN_TYPE_NONE,
334 frameline.TWEEN_TYPE_SHAPE) 489 frameline.TWEEN_TYPE_SHAPE)
335 _tween_obj_tween_types = (TweenObject.TWEEN_TYPE_NORMAL, 490 _tween_obj_tween_types = (TweenObject.TWEEN_TYPE_NORMAL,
336 TweenObject.TWEEN_TYPE_SCALE) 491 TweenObject.TWEEN_TYPE_SCALE)
337 _tween_type_names = ('normal', 'scale') 492 _tween_type_names = ('normal', 'scale')
338 493
339 def __init__(self, desktop, win, root=None): 494 def __init__(self, desktop, win, root=None):
495 super(MBScene, self).__init__()
496
340 self.desktop = desktop 497 self.desktop = desktop
341 self.window = win 498 self.window = win
342 self.layers = [] 499 self.layers = []
343 self.layers.append(Layer(None)) 500 self.layers.append(Layer(None))
344 self.scenemap = None 501 self.scenemap = None
380 self.button = gtk.Button('OK') 537 self.button = gtk.Button('OK')
381 vbox.pack_start(self.button) 538 vbox.pack_start(self.button)
382 self.button.connect("clicked", self.onQuit) 539 self.button.connect("clicked", self.onQuit)
383 self.window.add(vbox) 540 self.window.add(vbox)
384 pass 541 pass
385
386 def parseScene(self):
387 """
388 In this function, we will collect all items for the current
389 scene and then relocate them back to the appropriate scene
390 object.
391 """
392 self.layers = []
393 self.scenemap = None
394 doc = self.root
395
396 # TODO: Remove following code sicne this function is for parsing.
397 # Why do this here?
398 addEventListener(doc,'DOMNodeInserted',self.updateUI,None)
399 addEventListener(doc,'DOMNodeRemoved',self.updateUI,None)
400
401 doc.childList()
402 try:
403 self.width = float(doc.getAttribute("width"))
404 self.height= float(doc.getAttribute("height"))
405 except:
406 self.width = 640
407 self.height=480
408 pass
409
410 for node in doc.childList():
411 print node.name()
412 if node.name() == 'svg:metadata':
413 self.parseMetadata(node)
414 pass
415 elif node.name() == 'svg:g':
416 oldscene = None
417 lyobj = Layer(node)
418 self.layers.append(lyobj)
419 lyobj.current_scene = []
420 for scene in node.childList():
421 print scene.getCenter()
422 if scene.name() == 'svg:g':
423 try:
424 label = scene.getAttribute('inkscape:label')
425 if label == 'dup':
426 # TODO: remove this since this functio is for
427 # parsing. Why do this here?
428 node.removeChild(scene)
429 except:
430 pass
431
432 try:
433 scene_id = scene.getAttribute('id')
434 start, stop, tween_type = self.scenemap[scene_id]
435 except:
436 lyobj.current_scene.append(scene)
437 continue
438
439 lyobj.scenes.append(Scene(scene, start, stop,
440 tween_type))
441 pass
442 else:
443 lyobj.current_scene.append(scene)
444 pass
445 pass
446 pass
447 pass
448
449 # TODO: Remove following code, too. It is unreasonable.
450 self.collectID()
451 self.dumpID()
452 pass
453
454 def collectID(self):
455 self.ID = {}
456 root = self.root
457 for n in root.childList():
458 self.collectID_recursive(n)
459 pass
460 pass
461
462 def collectID_recursive(self,node):
463 try:
464 self.ID[node.getAttribute('id')] = 1
465 except:
466 pass
467 for n in node.childList():
468 self.collectID_recursive(n)
469 pass
470 pass
471
472 def getLayer(self, layer):
473 for l in self.layers:
474 if l.node.getAttribute('id') == layer:
475 return l
476 pass
477 return None
478
479 542
480 def removeKeyScene(self): 543 def removeKeyScene(self):
481 nth = self.last_frame 544 nth = self.last_frame
482 y = self.last_line 545 y = self.last_line
483 rdoc = self.document 546 rdoc = self.document
582 self.last_line.update() 645 self.last_line.update()
583 return 646 return
584 pass 647 pass
585 pass 648 pass
586 pass 649 pass
587
588
589 650
590 def setCurrentScene(self,nth): 651 def setCurrentScene(self,nth):
591 """ 652 """
592 Update the scene group according to the curretn scene 653 Update the scene group according to the curretn scene
593 data. There are a couple of cases. 654 data. There are a couple of cases.
864 old_node_id = old_node.getAttribute('id') 925 old_node_id = old_node.getAttribute('id')
865 new_node = new_nodes.next() 926 new_node = new_nodes.next()
866 new_node.setAttribute('ns0:duplicate-src', old_node_id) 927 new_node.setAttribute('ns0:duplicate-src', old_node_id)
867 pass 928 pass
868 929
869 gid = self.last_line.node.getAttribute("inkscape:label")+self.newID() 930 gid = self.last_line.node.getAttribute("inkscape:label")+self.new_id()
870 self.ID[gid]=1
871 ns.setAttribute("id",gid) 931 ns.setAttribute("id",gid)
872 ns.setAttribute("inkscape:groupmode","layer") 932 ns.setAttribute("inkscape:groupmode","layer")
873 self.last_line.node.appendChild(ns) 933 self.last_line.node.appendChild(ns)
874 return ns 934 return ns
875 935
1057 if not self.root: 1117 if not self.root:
1058 self.root = self.desktop.doc().root().repr 1118 self.root = self.desktop.doc().root().repr
1059 pass 1119 pass
1060 1120
1061 self.document = self.desktop.doc().rdoc 1121 self.document = self.desktop.doc().rdoc
1122 self.handle_doc_root(self.document, self.root)
1062 self.tween = TweenObject(self.document, self.root) 1123 self.tween = TweenObject(self.document, self.root)
1063 self._updateUI() 1124 self._updateUI()
1064 if self.top == None: 1125 if self.top == None:
1065 self.top = gtk.VBox(False,0) 1126 self.top = gtk.VBox(False,0)
1066 self.desktop.getToplevel().child.child.pack_end(self.top,expand=False) 1127 self.desktop.getToplevel().child.child.pack_end(self.top,expand=False)