Mercurial > MadButterfly
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) |