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 #