comparison pyink/domview.py @ 1345:e0400a2b7c35

Use trait instead of mixin for component_manager
author Thinker K.F. Li <thinker@codemud.net>
date Fri, 11 Feb 2011 15:10:37 +0800
parents 8f1f8ef5c9ea
children 22a79dcbaec6
comparison
equal deleted inserted replaced
1344:8f1f8ef5c9ea 1345:e0400a2b7c35
1 import random 1 import random
2 import dom_event 2 import dom_event
3 from tween import TweenObject 3 from tween import TweenObject
4 from trait import trait, require, composite
4 5
5 6
6 ## \brief Compare two nodes with ID. 7 ## \brief Compare two nodes with ID.
7 # 8 #
8 # \return True if node1 ID equivalent to ndoe2 ID. 9 # \return True if node1 ID equivalent to ndoe2 ID.
46 47
47 class Component(object): 48 class Component(object):
48 # 49 #
49 # \param comp_node is None for main component. 50 # \param comp_node is None for main component.
50 # 51 #
51 def __init__(self, domview, comp_node): 52 def __init__(self, comp_mgr, comp_node):
52 self._domview = domview 53 self._comp_mgr = comp_mgr
53 self.node = comp_node 54 self.node = comp_node
54 self.layers = [] 55 self.layers = []
55 self.timelines = [] 56 self.timelines = []
56 57
57 if comp_node: 58 if comp_node:
64 for child in comp_node.childList(): 65 for child in comp_node.childList():
65 if child.name() == 'ns0:scenes': 66 if child.name() == 'ns0:scenes':
66 break 67 break
67 pass 68 pass
68 else: # no any ns0:scenes 69 else: # no any ns0:scenes
69 doc = self._domview._doc 70 doc = self._comp_mgr._doc
70 scenes_node = doc.createElement('ns0:scenes') 71 scenes_node = doc.createElement('ns0:scenes')
71 scenes_node.setAttribute('name', 'default') 72 scenes_node.setAttribute('name', 'default')
72 73
73 node_id = self._domview.new_id() 74 node_id = self._comp_mgr.new_id()
74 scenes_node.setAttribute('id', node_id) 75 scenes_node.setAttribute('id', node_id)
75 76
76 comp_node.appendChild(scenes_node) 77 comp_node.appendChild(scenes_node)
77 pass 78 pass
78 pass 79 pass
124 def add_timeline(self, name): 125 def add_timeline(self, name):
125 if self.has_timeline(name): 126 if self.has_timeline(name):
126 raise ValueError, \ 127 raise ValueError, \
127 'try add a timeline with duplicated name - %s' % (name) 128 'try add a timeline with duplicated name - %s' % (name)
128 129
129 doc = self._domview._doc 130 doc = self._comp_mgr._doc
130 comp_node = self.node 131 comp_node = self.node
131 132
132 scenes_node = doc.createElement('ns0:scenes') 133 scenes_node = doc.createElement('ns0:scenes')
133 scenes_node.setAttribute('name', name) 134 scenes_node.setAttribute('name', name)
134 node_id = self._domview.new_id() 135 node_id = self._comp_mgr.new_id()
135 scenes_node.setAttribute('id', node_id) 136 scenes_node.setAttribute('id', node_id)
136 137
137 comp_node.appendChild(scenes_node) 138 comp_node.appendChild(scenes_node)
138 139
139 tl = Timeline(scenes_node) 140 tl = Timeline(scenes_node)
217 pass 218 pass
218 pass 219 pass
219 pass 220 pass
220 221
221 222
222 ## \brief A mix-in for class domview for management of components. 223 ## \brief A trait for class domview for managing components.
223 # 224 #
224 # This class is responsible for manage components and timelines. It 225 # This class is responsible for manage components and timelines. It
225 # is also responsible for switching component and timeline. Switching 226 # is also responsible for switching component and timeline. Switching
226 # to a component is actually switching to a timeline in another 227 # to a component is actually switching to a timeline in another
227 # component. When switch to a timeline, it actuall change 228 # component. When switch to a timeline, it actuall change
233 # 234 #
234 # FIXME: The root node is always the 'main' component. It is a 235 # FIXME: The root node is always the 'main' component. It is a
235 # special case with slightly different in structure. It should be 236 # special case with slightly different in structure. It should be
236 # removed and normalized to normal components. 237 # removed and normalized to normal components.
237 # 238 #
239 @trait
238 class component_manager(component_manager_ui_update): 240 class component_manager(component_manager_ui_update):
239 def __init__(self, domview): 241 _layers = require
242 _scenes_node = require
243 _metadata_node = require
244 _doc = require
245 _root = require
246 _layers = require
247 _layers_parent = require
248 new_id = require
249 get_node = require
250 reset = require
251
252 def __init__(self):
240 super(component_manager, self).__init__() 253 super(component_manager, self).__init__()
241 self._components_node = None 254 self._components_node = None
242 self._components = [] 255 self._components = []
243 self._comp_names = set() 256 self._comp_names = set()
244 self._main_comp = None 257 self._main_comp = None
245 self._cur_comp = None 258 self._cur_comp = None
246 self._cur_timeline = None 259 self._cur_timeline = None
247 self._components_group = None 260 self._components_group = None
248
249 self._domview = domview
250 pass 261 pass
251 262
252 def _set_main_component(self): 263 def _set_main_component(self):
253 comp = Component(self._domview, None) 264 comp = Component(self, None)
254 comp.layers = self._domview._layers 265 comp.layers = self._layers
255 scenes_node = self._domview._scenes_node 266 scenes_node = self._scenes_node
256 timeline = Timeline(scenes_node) 267 timeline = Timeline(scenes_node)
257 comp.timelines = [timeline] 268 comp.timelines = [timeline]
258 269
259 self._components.append(comp) 270 self._components.append(comp)
260 self._comp_names.add('main') 271 self._comp_names.add('main')
270 if child_name != 'ns0:component': 281 if child_name != 'ns0:component':
271 continue 282 continue
272 if child_name in comp_names: 283 if child_name in comp_names:
273 raise ValueError, 'duplicate component name %s' % (child_name) 284 raise ValueError, 'duplicate component name %s' % (child_name)
274 285
275 comp = Component(self._domview, child) 286 comp = Component(self, child)
276 comp.parse_timelines() 287 comp.parse_timelines()
277 288
278 self._components.append(comp) 289 self._components.append(comp)
279 comp_names.add(child_name) 290 comp_names.add(child_name)
280 pass 291 pass
283 ## \brief To initialize subtree of metadata. 294 ## \brief To initialize subtree of metadata.
284 # 295 #
285 # This method is called by domview._init_metadata(). 296 # This method is called by domview._init_metadata().
286 # 297 #
287 def _component_manager_init_metadata(self): 298 def _component_manager_init_metadata(self):
288 metadata_node = self._domview._metadata_node 299 metadata_node = self._metadata_node
289 300
290 # Make sure ns0:components in metadata 301 # Make sure ns0:components in metadata
291 for n in metadata_node.childList(): 302 for n in metadata_node.childList():
292 if n.name() == 'ns0:components': 303 if n.name() == 'ns0:components':
293 self._components_node = n 304 self._components_node = n
294 break 305 break
295 pass 306 pass
296 else: 307 else:
297 components_node = \ 308 components_node = \
298 self._domview._doc.createElement("ns0:components") 309 self._doc.createElement("ns0:components")
299 metadata_node.appendChild(components_node) 310 metadata_node.appendChild(components_node)
300 self._components_node = components_node 311 self._components_node = components_node
301 pass 312 pass
302 313
303 # Make sure the group for containing components. 314 # Make sure the group for containing components.
304 for n in self._domview._root.childList(): 315 for n in self._root.childList():
305 if n.name() != 'svg:g': 316 if n.name() != 'svg:g':
306 continue 317 continue
307 try: 318 try:
308 nlabel = n.getAttribute('inkscape:label') 319 nlabel = n.getAttribute('inkscape:label')
309 except: 320 except:
311 if nlabel == 'components': 322 if nlabel == 'components':
312 self._components_group 323 self._components_group
313 break 324 break
314 pass 325 pass
315 else: # no components group 326 else: # no components group
316 components_group = self._domview._doc.createElement('svg:g') 327 components_group = self._doc.createElement('svg:g')
317 components_group.setAttribute('inkscape:label', 'components') 328 components_group.setAttribute('inkscape:label', 'components')
318 gid = self._domview.new_id() 329 gid = self.new_id()
319 components_group.setAttribute('id', gid) 330 components_group.setAttribute('id', gid)
320 331
321 self._domview._root.appendChild(components_group) 332 self._root.appendChild(components_group)
322 self._components_group = components_group 333 self._components_group = components_group
323 pass 334 pass
324 pass 335 pass
325 336
326 def _start_component_manager(self): 337 def _start_component_manager(self):
329 self._parse_components() 340 self._parse_components()
330 341
331 self._cur_comp = self._main_comp 342 self._cur_comp = self._main_comp
332 tl = self._main_comp.get_timeline('default') 343 tl = self._main_comp.get_timeline('default')
333 self._cur_timeline = tl 344 self._cur_timeline = tl
334 self._domview._scenes_node = tl.scenes_node 345 self._scenes_node = tl.scenes_node
335 pass 346 pass
336 347
337 ## \brief Create component group 348 ## \brief Create component group
338 # 349 #
339 # A component group is a group with a layers group as child. 350 # A component group is a group with a layers group as child.
340 # The layers group is where layer groups is in. 351 # The layers group is where layer groups is in.
341 # 352 #
342 def _create_component_group(self): 353 def _create_component_group(self):
343 doc = self._domview._doc 354 doc = self._doc
344 group = doc.createElement('svg:g') 355 group = doc.createElement('svg:g')
345 gid = self._domview.new_id() 356 gid = self.new_id()
346 group.setAttribute('id', gid) 357 group.setAttribute('id', gid)
347 358
348 self._components_group.appendChild(group) 359 self._components_group.appendChild(group)
349 360
350 # Create layers group 361 # Create layers group
351 layers_group = doc.createElement('svg:g') 362 layers_group = doc.createElement('svg:g')
352 gid = self._domview.new_id() 363 gid = self.new_id()
353 layers_group.setAttribute('id', gid) 364 layers_group.setAttribute('id', gid)
354 layers_group.setAttribute('inkscape:label', 'layers') 365 layers_group.setAttribute('inkscape:label', 'layers')
355 group.appendChild(layers_group) 366 group.appendChild(layers_group)
356 367
357 return group 368 return group
361 # \param comp_name is the name of the created component. 372 # \param comp_name is the name of the created component.
362 # \param comp_group_id is the component group. 373 # \param comp_group_id is the component group.
363 # \return a ns0:component node. 374 # \return a ns0:component node.
364 # 375 #
365 def _create_component_node(self, comp_name, comp_group_id): 376 def _create_component_node(self, comp_name, comp_group_id):
366 comp_node = self._domview._doc.createElement('ns0:component') 377 comp_node = self._doc.createElement('ns0:component')
367 comp_id = self._domview.new_id() 378 comp_id = self.new_id()
368 comp_node.setAttribute('id', comp_id) 379 comp_node.setAttribute('id', comp_id)
369 comp_node.setAttribute('name', comp_name) 380 comp_node.setAttribute('name', comp_name)
370 comp_node.setAttribute('ref', comp_group_id) 381 comp_node.setAttribute('ref', comp_group_id)
371 self._components_node.appendChild(comp_node) 382 self._components_node.appendChild(comp_node)
372 return comp_node 383 return comp_node
383 raise ValueError, 'can not find component node - %s' % (comp_name) 394 raise ValueError, 'can not find component node - %s' % (comp_name)
384 395
385 ## \brief Create a layer group for give layer of a component. 396 ## \brief Create a layer group for give layer of a component.
386 # 397 #
387 def _create_comp_layer_group(self, layers_group, layer_name): 398 def _create_comp_layer_group(self, layers_group, layer_name):
388 doc = self._domview._doc 399 doc = self._doc
389 gid = self._domview.new_id() 400 gid = self.new_id()
390 401
391 layer_group = doc.createElement('svg:g') 402 layer_group = doc.createElement('svg:g')
392 layer_group.setAttribute('id', gid) 403 layer_group.setAttribute('id', gid)
393 layer_group.setAttribute('inkscape:label', layer_name) 404 layer_group.setAttribute('inkscape:label', layer_name)
394 layer_group.setAttribute('inkscape:groupmode', 'layer') 405 layer_group.setAttribute('inkscape:groupmode', 'layer')
406 layer = comp.layers[layer_idx] 417 layer = comp.layers[layer_idx]
407 return layer.group 418 return layer.group
408 419
409 def _get_layers_group_of_component(self, comp_name): 420 def _get_layers_group_of_component(self, comp_name):
410 if comp_name == 'main': 421 if comp_name == 'main':
411 return self._domview._root 422 return self._root
412 423
413 comp_group = self.get_component_group(comp_name) 424 comp_group = self.get_component_group(comp_name)
414 layers_group = comp_group.firstChild() 425 layers_group = comp_group.firstChild()
415 assert layers_group.getAttribute('inkscape:label') == 'layers' 426 assert layers_group.getAttribute('inkscape:label') == 'layers'
416 427
451 def switch_component(self, comp_name): 462 def switch_component(self, comp_name):
452 old_comp = self._cur_comp 463 old_comp = self._cur_comp
453 464
454 comp = self._get_component(comp_name) 465 comp = self._get_component(comp_name)
455 self._cur_comp = comp 466 self._cur_comp = comp
456 self._domview._layers = comp.layers 467 self._layers = comp.layers
457 comp_name = self._cur_comp.name() 468 comp_name = self._cur_comp.name()
458 # for domview 469 # for domview
459 self._domview._layers_parent = \ 470 self._layers_parent = \
460 self._get_layers_group_of_component(comp_name) 471 self._get_layers_group_of_component(comp_name)
461 472
462 first_name = comp.all_timeline_names()[0] 473 first_name = comp.all_timeline_names()[0]
463 self.switch_timeline(first_name) 474 self.switch_timeline(first_name)
464 475
473 484
474 comp_group = self._create_component_group() 485 comp_group = self._create_component_group()
475 comp_group_id = comp_group.getAttribute('id') 486 comp_group_id = comp_group.getAttribute('id')
476 comp_node = self._create_component_node(comp_name, comp_group_id) 487 comp_node = self._create_component_node(comp_name, comp_group_id)
477 488
478 comp = Component(self._domview, comp_node) 489 comp = Component(self, comp_node)
479 comp.parse_timelines() 490 comp.parse_timelines()
480 491
481 self._components.append(comp) 492 self._components.append(comp)
482 self._comp_names.add(comp_name) 493 self._comp_names.add(comp_name)
483 494
489 500
490 self.hide_component(comp_name) 501 self.hide_component(comp_name)
491 pass 502 pass
492 503
493 def add_component_node(self, comp_node): 504 def add_component_node(self, comp_node):
494 comp = Component(self._domview, comp_node) 505 comp = Component(self, comp_node)
495 comp_name = comp.name() 506 comp_name = comp.name()
496 if self.has_component(comp_name): 507 if self.has_component(comp_name):
497 raise ValueError, \ 508 raise ValueError, \
498 'the name of a ns0:component is duplicated' 509 'the name of a ns0:component is duplicated'
499 510
521 def get_component_group(self, comp_name): 532 def get_component_group(self, comp_name):
522 comp = self._get_component(comp_name) 533 comp = self._get_component(comp_name)
523 534
524 comp_name = comp.name() 535 comp_name = comp.name()
525 if comp_name == 'main': 536 if comp_name == 'main':
526 return self._domview._root 537 return self._root
527 538
528 comp_node = comp.node 539 comp_node = comp.node
529 gid = comp_node.getAttribute('ref') 540 gid = comp_node.getAttribute('ref')
530 comp_group = self._domview.get_node(gid) 541 comp_group = self.get_node(gid)
531 return comp_group 542 return comp_group
532 543
533 def get_current_component(self): 544 def get_current_component(self):
534 return self._cur_comp.name() 545 return self._cur_comp.name()
535 546
542 scenes_node = tl.scenes_node 553 scenes_node = tl.scenes_node
543 for child in scenes_node.childList(): 554 for child in scenes_node.childList():
544 if child.name() != 'ns0:scene': 555 if child.name() != 'ns0:scene':
545 continue 556 continue
546 gid = child.getAttribute('ref') 557 gid = child.getAttribute('ref')
547 group = self._domview.get_node(gid) 558 group = self.get_node(gid)
548 group.setAttribute('style', 'display: none') 559 group.setAttribute('style', 'display: none')
549 pass 560 pass
550 pass 561 pass
551 562
552 def switch_timeline(self, timeline_name): 563 def switch_timeline(self, timeline_name):
554 self._hide_current_timeline() 565 self._hide_current_timeline()
555 pass 566 pass
556 567
557 tl = self._cur_comp.get_timeline(timeline_name) 568 tl = self._cur_comp.get_timeline(timeline_name)
558 self._cur_timeline = tl 569 self._cur_timeline = tl
559 self._domview._scenes_node = tl.scenes_node # of class domview 570 self._scenes_node = tl.scenes_node # of class domview
560 571
561 # Make domview to rescan layers and scenes. 572 # Make domview to rescan layers and scenes.
562 self._domview.reset() # from domview 573 self.reset() # from domview
563 pass 574 pass
564 575
565 def add_timeline(self, timeline_name): 576 def add_timeline(self, timeline_name):
566 self._cur_comp.add_timeline(timeline_name) 577 self._cur_comp.add_timeline(timeline_name)
567 pass 578 pass
612 # \return link node. 623 # \return link node.
613 # 624 #
614 def link_to_component(self, comp_name, parent_group): 625 def link_to_component(self, comp_name, parent_group):
615 layers_group = self._get_layers_group_of_component(comp_name) 626 layers_group = self._get_layers_group_of_component(comp_name)
616 627
617 use_node = self._domview._doc.createElement('svg:use') 628 use_node = self._doc.createElement('svg:use')
618 layers_group_id = layers_group.getAttribute('id') 629 layers_group_id = layers_group.getAttribute('id')
619 use_node.setAttribute('xlink:href', '#' + layers_group_id) 630 use_node.setAttribute('xlink:href', '#' + layers_group_id)
620 use_node_id = self._domview.new_id() 631 use_node_id = self.new_id()
621 use_node.setAttribute('id', use_node_id) 632 use_node.setAttribute('id', use_node_id)
622 use_node.setAttribute('use_component', 'true') 633 use_node.setAttribute('use_component', 'true')
623 634
624 parent_group.appendChild(use_node) 635 parent_group.appendChild(use_node)
625 636
960 # 971 #
961 # This class maintains layers information, and provides functions to create, 972 # This class maintains layers information, and provides functions to create,
962 # change and destroy scene node and scene group. A scene node is a 'ns0:scene' 973 # change and destroy scene node and scene group. A scene node is a 'ns0:scene'
963 # in 'ns0:scenes' tag. A scene group is respective 'svg:g' for a scene. 974 # in 'ns0:scenes' tag. A scene group is respective 'svg:g' for a scene.
964 # 975 #
976 @composite
965 class domview(domview_monitor): 977 class domview(domview_monitor):
978 use_traits = (component_manager,)
979
980 method_map_component_manager = \
981 {component_manager._start_component_manager:
982 '_start_component_manager'}
983 method_map_traits = {component_manager: method_map_component_manager}
984
966 # Declare variables, here, for keeping tracking 985 # Declare variables, here, for keeping tracking
967 _doc = None 986 _doc = None
968 _root = None 987 _root = None
969 988
970 def __init__(self, *args, **kws): 989 def __init__(self, *args, **kws):
975 # component_manager to switch components and timelines. 994 # component_manager to switch components and timelines.
976 # 995 #
977 self._scenes_node = None 996 self._scenes_node = None
978 self._layers_parent = None 997 self._layers_parent = None
979 self._layers = [] 998 self._layers = []
980
981 self._comp_mgr = component_manager(self)
982 # Mixing-in component_manager to domview.
983 for attr in dir(self._comp_mgr):
984 if not attr.startswith('_'):
985 v = getattr(self._comp_mgr, attr)
986 setattr(self, attr, v)
987 pass
988 pass
989 pass 999 pass
990 1000
991 ## \brief Create a scenes node if not existed. 1001 ## \brief Create a scenes node if not existed.
992 # 1002 #
993 def _init_metadata(self): 1003 def _init_metadata(self):
1050 self._root = root 1060 self._root = root
1051 self._layers[:] = [] 1061 self._layers[:] = []
1052 1062
1053 self._init_metadata() 1063 self._init_metadata()
1054 self._start_monitor() # from domview_monitor 1064 self._start_monitor() # from domview_monitor
1055 self._comp_mgr._start_component_manager() 1065 self._start_component_manager()
1056 self._parse_all_layers() 1066 self._parse_all_layers()
1057 pass 1067 pass
1058 1068
1059 def reset(self): 1069 def reset(self):
1060 self._monitor_reparse() # from domview_monitor 1070 self._monitor_reparse() # from domview_monitor