Mercurial > MadButterfly
comparison pyink/domview.py @ 1463:5ff744b981fb
FSM manager and data types
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Sun, 17 Apr 2011 21:29:16 +0800 |
parents | 8eecaca2a125 |
children | a3ce8d22d163 |
comparison
equal
deleted
inserted
replaced
1462:c3e0af5d2487 | 1463:5ff744b981fb |
---|---|
46 scenes_node.setAttribute('name', new_name) | 46 scenes_node.setAttribute('name', new_name) |
47 pass | 47 pass |
48 pass | 48 pass |
49 | 49 |
50 | 50 |
51 class Transition(object): | |
52 node = None | |
53 condition = None | |
54 target = None | |
55 action = None | |
56 | |
57 def __init__(self, node=None): | |
58 self.node = node | |
59 pass | |
60 | |
61 def set_condition(self, cond): | |
62 node = self.node | |
63 | |
64 node.setAttribute('condition', cond) | |
65 self.condition = cond | |
66 pass | |
67 | |
68 def set_action(self, action): | |
69 self.action = action | |
70 node = self.node | |
71 node.setAttribute('action', action) | |
72 pass | |
73 | |
74 def reparse(self): | |
75 condition = node.getAttribute('condition') | |
76 target = node.getAttribute('target') | |
77 try: | |
78 action = node.getAttribute('action') | |
79 except: | |
80 action = None | |
81 pass | |
82 | |
83 self.condition = condition | |
84 self.target = target | |
85 self.action = action | |
86 pass | |
87 | |
88 def update_node(self): | |
89 node = self.node | |
90 node.setAttribute('condition', self.condition) | |
91 node.setAttribute('target', self.target) | |
92 if self.action: | |
93 node.setAttribute('action', self.action) | |
94 pass | |
95 pass | |
96 | |
97 ## \brief Create a node according status of the object. | |
98 # | |
99 # A new node is created for the object, and attributes of the node | |
100 # is initialized with information from the object. | |
101 # | |
102 def create_node(self, doc): | |
103 node = doc.createElement('ns0:transition') | |
104 self.node = node | |
105 self.update_node() | |
106 | |
107 return node | |
108 | |
109 @staticmethod | |
110 def parse_transition(node): | |
111 trn = Transition(node) | |
112 trn.reparse() | |
113 return trn | |
114 pass | |
115 | |
116 | |
117 ## \brief A state in a FSM | |
118 # | |
119 # Every component can have a FSM to describe its behavior. Every | |
120 # state has an entry action and transitions to other states. Every | |
121 # transition can have a transition action. | |
122 # | |
123 # The FSM of a component is defined as a child of ns0:component node. | |
124 # \verbatim | |
125 # <ns0:component> | |
126 # <ns0:states start_state="UP"> | |
127 # <ns0:state name="UP" entry_action="entry action"> | |
128 # <ns0:transition target="DOWN" | |
129 # condition="button_down" action="..."/> | |
130 # </ns0:state> | |
131 # </ns0:states> | |
132 # </ns0:/component> | |
133 # \endverbatim | |
134 # | |
135 class State(object): | |
136 name = None | |
137 entry_action = None | |
138 transitions = None | |
139 | |
140 def __init__(self, node): | |
141 self.node = node | |
142 pass | |
143 | |
144 def rename(self, name): | |
145 self.name = name | |
146 self.node.setAttribute('name', name) | |
147 pass | |
148 | |
149 def set_entry_action(self, action): | |
150 self.entry_action = action | |
151 self.node.setAttribute('entry_action', action) | |
152 pass | |
153 | |
154 def reparse(self): | |
155 node = self.node | |
156 | |
157 name = node.getAttribute('name') | |
158 try: | |
159 entry_action = node.getAttribute('entry_action') | |
160 except: | |
161 entry_action = None | |
162 pass | |
163 | |
164 all_transitions = [Transition.parse_transition(child) | |
165 for child in node.childList() | |
166 if child.name() == 'ns0:transition'] | |
167 transitions = dict([(trn.condition, trn) | |
168 for trn in all_transitions]) | |
169 | |
170 self.name = name | |
171 self.transitions = transitions | |
172 self.entry_action = entry_action | |
173 pass | |
174 | |
175 def update_node(self): | |
176 node = self.node | |
177 | |
178 node.setAttribute('name', self.name) | |
179 if self.entry_action: | |
180 node.setAttribute('entry_action', self.entry_action) | |
181 pass | |
182 | |
183 transitions = self.transitions or [] | |
184 for trn in transitions: | |
185 trn.update_node() | |
186 pass | |
187 pass | |
188 | |
189 def create_node(self, doc): | |
190 node = doc.createElement('ns0:state') | |
191 self.node = node | |
192 | |
193 self.update_node() | |
194 | |
195 return node | |
196 | |
197 @staticmethod | |
198 def parse_state(node): | |
199 state = State(node) | |
200 state.parse() | |
201 | |
202 return state | |
203 | |
204 def change_transition_cond(self, old_cond, new_cond): | |
205 transitions = self.transitions | |
206 trn = transitions[old_cond] | |
207 del transitions[old_cond] | |
208 transitions[new_cond] = trn | |
209 | |
210 trn.set_condition(new_cond) | |
211 pass | |
212 | |
213 def add_transition(self, cond, target): | |
214 transitions = self.transitions | |
215 assert cond not in transitions | |
216 | |
217 node = self.node | |
218 | |
219 trn = Transition() | |
220 trn.condition = cond | |
221 trn.target = target | |
222 trn_node = trn.create_node(node.document()) | |
223 | |
224 node.addChild(trn_node) | |
225 transitions[cond] = trn | |
226 pass | |
227 | |
228 def rm_transition(self, cond): | |
229 transitions = self.transitions | |
230 if cond not in transitions: | |
231 raise ValueError, \ | |
232 'There is no transition defined for this condition (%s)' % \ | |
233 (cond) | |
234 | |
235 trn = transitions[cond] | |
236 trn_node = trn.node | |
237 node = self.node | |
238 | |
239 node.removeChild(trn_node) | |
240 del transitions[cond] | |
241 pass | |
242 | |
243 def all_transitions(self): | |
244 return self.transitions.keys() | |
245 | |
246 def get_transition(self, cond): | |
247 transitions = self.transitions | |
248 transition = transitions[cond] | |
249 return transition | |
250 pass | |
251 | |
252 | |
51 class Component(object): | 253 class Component(object): |
52 # | 254 # |
53 # \param comp_node is None for main component. | 255 # \param comp_node is None for main component. |
54 # | 256 # |
55 def __init__(self, comp_mgr, comp_node): | 257 def __init__(self, comp_mgr, comp_node): |
56 self._comp_mgr = comp_mgr | 258 self._comp_mgr = comp_mgr |
57 self.node = comp_node | 259 self.node = comp_node |
58 self.layers = [] | 260 self.layers = [] |
59 self.timelines = [] | 261 self.timelines = [] |
262 self.fsm_states = {} | |
263 self.fsm_states_node = None | |
264 self.fsm_start_state = None | |
60 | 265 |
61 if comp_node: | 266 if comp_node: |
62 self._initialize_comp() | 267 self._initialize_comp() |
63 pass | 268 pass |
64 pass | 269 pass |
108 print ' ' + tl.name() | 313 print ' ' + tl.name() |
109 pass | 314 pass |
110 pass | 315 pass |
111 pass | 316 pass |
112 | 317 |
318 ## \brief Parse FSM from a ns0:states node. | |
319 # | |
320 def parse_states(self): | |
321 comp_node = self.node | |
322 assert (not comp_node) or comp_node.name() == 'ns0:component' | |
323 | |
324 states_nodes = [node | |
325 for node in comp_node.childList() | |
326 if node.name() == 'ns0:states'] | |
327 if not states_nodes: | |
328 self.fsm_states = {} | |
329 return | |
330 states_node = states_nodes[0] | |
331 | |
332 self.fsm_start_state = states_node.getAttribute('start_state') | |
333 | |
334 state_nodes = [child | |
335 for child in states_node.childList | |
336 if child.name() == 'ns0:state'] | |
337 states = [State.parse_state(node) for state_node in state_nodes] | |
338 self.fsm_states = dict([(state.name, state) for state in states]) | |
339 | |
340 self.fsm_states_node = states_node | |
341 pass | |
342 | |
113 def get_timeline(self, name): | 343 def get_timeline(self, name): |
114 for tl in self.timelines: | 344 for tl in self.timelines: |
115 if tl.name() == name: | 345 if tl.name() == name: |
116 return tl | 346 return tl |
117 pass | 347 pass |
174 pass | 404 pass |
175 raise ValueError, 'try to remove a non-existed timeline - %s' % (name) | 405 raise ValueError, 'try to remove a non-existed timeline - %s' % (name) |
176 | 406 |
177 def rename(self, new_name): | 407 def rename(self, new_name): |
178 self.node.setAttribute('name', new_name) | 408 self.node.setAttribute('name', new_name) |
409 pass | |
410 | |
411 def get_start_state_name(self): | |
412 return self.fsm_start_state | |
413 | |
414 def set_start_state(self, state_name): | |
415 assert state_name in self.fsm_states | |
416 self.fsm_start_state = state_name | |
417 pass | |
418 | |
419 def all_state_names(self): | |
420 return self.fsm_states.keys() | |
421 | |
422 def get_state(self, name): | |
423 return self.fsm_states[name] | |
424 | |
425 def add_state(self, name): | |
426 doc = self._comp_mgr._doc | |
427 | |
428 state = State(name) | |
429 state.transitions = [] | |
430 self.fsm_states[name] = state | |
431 | |
432 state_node = state.create_node(doc) | |
433 node = self.node | |
434 node.addChild(state_node) | |
435 pass | |
436 | |
437 def rename_state(self, state_name, new_name): | |
438 state = self.fsm_states[state_name] | |
439 del self.fsm_states[state_name] | |
440 self.fsm_states[new_name] = state | |
441 | |
442 state.rename(new_name) | |
443 pass | |
444 | |
445 def rm_state(self, name): | |
446 fsm_states = self.fsm_states | |
447 state = fsm_states[name] | |
448 del self.fsm_states[name] | |
449 | |
450 state_node = state.node | |
451 node = self.node | |
452 node.removeChild(state_node) | |
179 pass | 453 pass |
180 pass | 454 pass |
181 | 455 |
182 | 456 |
183 ## \brief A mix-in for class component_manager for UI updating. | 457 ## \brief A mix-in for class component_manager for UI updating. |
244 _metadata_node = require | 518 _metadata_node = require |
245 _doc = require | 519 _doc = require |
246 _root = require | 520 _root = require |
247 _layers = require | 521 _layers = require |
248 _layers_parent = require | 522 _layers_parent = require |
523 _cur_comp = require | |
249 new_id = require | 524 new_id = require |
250 get_node = require | 525 get_node = require |
251 reset = require | 526 reset = require |
252 | 527 |
253 def __init__(self): | 528 def __init__(self): |
254 super(component_manager, self).__init__() | 529 super(component_manager, self).__init__() |
255 self._components_node = None | 530 self._components_node = None |
256 self._components = [] | 531 self._components = [] |
257 self._comp_names = set() | 532 self._comp_names = set() |
258 self._main_comp = None | 533 self._main_comp = None |
259 self._cur_comp = None | |
260 self._cur_timeline = None | 534 self._cur_timeline = None |
261 self._components_group = None | 535 self._components_group = None |
262 pass | 536 pass |
263 | 537 |
264 def _set_main_component(self): | 538 def _set_main_component(self): |
702 else: | 976 else: |
703 cur_frame_idx = int(cur_frame) | 977 cur_frame_idx = int(cur_frame) |
704 pass | 978 pass |
705 | 979 |
706 return cur_layer_idx, cur_frame_idx | 980 return cur_layer_idx, cur_frame_idx |
981 pass | |
982 | |
983 | |
984 ## \brief A trait for management FSM associated with current component. | |
985 # | |
986 @trait | |
987 class FSM_manager(object): | |
988 _cur_comp = require | |
989 | |
990 def __init__(self): | |
991 super(FSM_manager, self).__init__() | |
992 pass | |
993 | |
994 def all_state_names(self): | |
995 return self._cur_comp.all_state_names() | |
996 | |
997 def get_start_state_name(self): | |
998 return self._cur_comp.get_start_state_name() | |
999 | |
1000 ## \brief To return state object for the given name. | |
1001 # | |
1002 # This method should only be used by component_manager internally. | |
1003 # | |
1004 def _get_state(self, state_name): | |
1005 return self._cur_comp.get_state(state_name) | |
1006 | |
1007 def rm_state(self, state_name): | |
1008 self._cur_comp.rm_state(state_name) | |
1009 pass | |
1010 | |
1011 def add_state(self, state_name): | |
1012 self._cur_comp.add_state(state_name) | |
1013 pass | |
1014 | |
1015 def rename_state(self, state_name, new_name): | |
1016 self._cur_comp.rename_state(state_name, new_name) | |
1017 pass | |
1018 | |
1019 def set_start_state(self, state_name): | |
1020 self._cur_comp.set_start_state(state_name) | |
1021 pass | |
1022 | |
1023 def set_state_entry_action(self, state_name, entry_action): | |
1024 state = self._get_state(state_name) | |
1025 state.set_entry_action(entry_action) | |
1026 pass | |
1027 | |
1028 def all_transitions(self, state_name): | |
1029 state = self._get_state(state_name) | |
1030 trn_names = state.all_transitions() | |
1031 return trn_names | |
1032 | |
1033 def add_transition(self, state_name, cond, target): | |
1034 state = self._get_state(state_name) | |
1035 state.add_transition(cond, target) | |
1036 pass | |
1037 | |
1038 def rm_transition(self, state_name, cond): | |
1039 state = self._get_state(state_name) | |
1040 state.rm_transition(cond) | |
1041 pass | |
1042 | |
1043 def change_transition_cond(self, state_name, old_cond, new_cond): | |
1044 state = self._get_state(state_name) | |
1045 state.change_transition_cond(old_cond, new_cond) | |
1046 pass | |
1047 | |
1048 def get_transition(self, state_name, cond): | |
1049 state = self._get_state(state_name) | |
1050 trn = state.get_transition(cond) | |
1051 | |
1052 cond = trn.condition | |
1053 target = trn.target | |
1054 action = trn.action | |
1055 | |
1056 return cond, target, action | |
1057 | |
1058 def set_transition_action(self, state_name, cond, action): | |
1059 trn = state.get_transition(state_name, cond) | |
1060 trn.set_action(action) | |
1061 pass | |
707 pass | 1062 pass |
708 | 1063 |
709 | 1064 |
710 ## \brief Parser for scenes nodes. | 1065 ## \brief Parser for scenes nodes. |
711 # | 1066 # |
1272 # change and destroy scene node and scene group. A scene node is a 'ns0:scene' | 1627 # change and destroy scene node and scene group. A scene node is a 'ns0:scene' |
1273 # in 'ns0:scenes' tag. A scene group is respective 'svg:g' for a scene. | 1628 # in 'ns0:scenes' tag. A scene group is respective 'svg:g' for a scene. |
1274 # | 1629 # |
1275 @composite | 1630 @composite |
1276 class domview(domview_monitor): | 1631 class domview(domview_monitor): |
1277 use_traits = (component_manager, layers_parser) | 1632 use_traits = (component_manager, layers_parser, FSM_manager) |
1278 | 1633 |
1279 method_map_traits = {component_manager._start_component_manager: | 1634 method_map_traits = {component_manager._start_component_manager: |
1280 '_start_component_manager'} | 1635 '_start_component_manager'} |
1281 | 1636 |
1282 # Declare variables, here, for keeping tracking | 1637 # Declare variables, here, for keeping tracking |
1283 _doc = None | 1638 _doc = None |
1284 _root = None | 1639 _root = None |
1640 # Required by component_manager and FSM_manager | |
1641 _cur_comp = None | |
1285 | 1642 |
1286 def __init__(self, *args, **kws): | 1643 def __init__(self, *args, **kws): |
1287 super(domview, self).__init__() | 1644 super(domview, self).__init__() |
1288 self._metadata_node = None | 1645 self._metadata_node = None |
1289 # | 1646 # |