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