# HG changeset patch # User Thinker K.F. Li # Date 1303619447 -28800 # Node ID c1e70540541c58d584ec06a6fb2fcc6eeec7bcc5 # Parent c586981ecf1a5c1a32e5a9bc98b10f068f5c3793 Drawing functions for states and transitions diff -r c586981ecf1a -r c1e70540541c pyink/FSM_window.py --- a/pyink/FSM_window.py Mon Apr 18 11:54:10 2011 +0800 +++ b/pyink/FSM_window.py Sun Apr 24 12:30:47 2011 +0800 @@ -68,13 +68,122 @@ self._locker = domview_ui self._domview = domview_ui + self._state_nodes = {} self._close_cb = close_cb # callback to close editor window (hide) self._destroy_cb = destroy_cb # callback to destroy editor window pass + def _doc(self): + view_widget = self._view_widget + view = view_widget.view + doc = view.doc().rdoc + return doc + + def _root(self): + doc = self._doc() + root = doc.root() + return root + + def _clear_view(self): + root = self._root() + + children = [child for child in root.childList() + if child.name() == 'svg:g'] + for child in children: + root.removeChild(child) + pass + + self._state_nodes = {} + pass + + def _draw_transition_real(self, state_g, path): + import math + doc = self._doc() + + path_node = doc.createElement('svg:path') + path_txt = 'M %f,%f C %f,%f %f,%f %f,%f' % tuple(path) + path_node.setAttribute('d', path_txt) + path_node.setAttribute('style', 'stroke: #000000; stroke-width: 1; ' + 'fill: none') + state_g.appendChild(path_node) + + # c0 c1 c2 c3 of cubic curve + c3 = (path[6], path[7]) + c2 = (path[4], path[5]) + c23_v = (c3[0] - c2[0], c3[1] - c2[1]) + c23_len = math.sqrt(c23_v[0] * c23_v[0] + c23_v[1] * c23_v[1]) + adir = (c23_v[0] / c23_len, c23_v[1] / c23_len) # arrow direction + odir = (-adir[1], adir[0]) # othogonal direction + arrow_pts = (c3[0], c3[1], + -adir[0] * 10 + odir[0] * 4, -adir[1] * 10 + odir[1] * 4, + -odir[0] * 8, -odir[1] * 8) + arrow_txt = 'M %f,%f l %f,%f l %f,%f z' % arrow_pts + arrow_node = doc.createElement('svg:path') + arrow_node.setAttribute('d', arrow_txt) + arrow_node.setAttribute('style', 'stroke: #000000; stroke-width: 1; ' + 'fill: #000000') + state_g.appendChild(arrow_node) + pass + + def _draw_state_real(self, state_name, r, x, y): + doc = self._doc() + root = self._root() + + state_g = doc.createElement('svg:g') + state_g.setAttribute('inkscape:groupmode', 'layer') + + circle = doc.createElement('svg:circle') + circle.setAttribute('r', str(r)) + circle.setAttribute('cx', str(x)) + circle.setAttribute('cy', str(y)) + circle.setAttribute('style', 'stroke: #000000; stroke-width: 1; ' + 'fill: #ffffff') + state_g.appendChild(circle) + + text = doc.createElement('svg:text') + text_content = doc.createTextNode(state_name) + text.appendChild(text_content) + text.setAttribute('font-size', '16') + text.setAttribute('style', 'stroke: #000000; fill: #000000') + state_g.appendChild(text) + + root.appendChild(state_g) + + tx, ty, tw, th = text.getBBox() + text.setAttribute('x', str(x - tw / 2)) + text.setAttribute('y', str(y + th / 2)) + + return state_g + + def _draw_state(self, state_name): + domview = self._domview + + r = domview.get_state_r(state_name) + x, y = domview.get_state_xy(state_name) + state_g = self._draw_state_real(state_name, r, x, y) + self._state_nodes[state_name] = state_g + + transitions = [domview.get_transition(state_name, trn_name)[3] + for trn_name in domview.all_transitions()] + for trn in transitions: + self._draw_transition_real(state_g, trn) + pass + pass + + def _update_view(self): + self._clear_view() + + domview = self._domview + state_names = domview.all_state_names() + for state_name in state_names: + self._draw_state(state_name) + pass + pass + def set_svg_view(self, view): self._view_box.add(view) + self._view_widget = view pass def on_close_window_activate(self, *args): @@ -94,6 +203,34 @@ domview.add_state('test0') domview.add_state('test1') domview.add_transition('test0', 'event1', 'test1') + + view = self._view_widget.view + doc = view.doc() + rdoc = doc.rdoc + root_node = doc.root().repr + + line_node = rdoc.createElement('svg:line') + line_node.setAttribute('x1', '10') + line_node.setAttribute('y1', '10') + line_node.setAttribute('x2', '100') + line_node.setAttribute('y2', '100') + line_node.setAttribute('style', 'stroke: #000000; stroke-width:2') + + print root_node.name() + print root_node.childList()[-1].name() + root_node.setAttribute('inkscape:groupmode', 'layer') + root_node.appendChild(line_node) + + def show_msg(*args, **kws): + print 'mouse_event' + print args + pass + print 'before connect' + hdl_id = line_node.spitem.connect('mouse-event', show_msg) + print hdl_id + + state_g = self._draw_state_real('test1', 40, 100, 50) + self._draw_transition_real(state_g, (100, 100, 140, 120, 160, 120, 200, 100)) pass pass diff -r c586981ecf1a -r c1e70540541c pyink/domview.py --- a/pyink/domview.py Mon Apr 18 11:54:10 2011 +0800 +++ b/pyink/domview.py Sun Apr 24 12:30:47 2011 +0800 @@ -53,6 +53,7 @@ condition = None target = None action = None + path = None def __init__(self, node=None): self.node = node @@ -71,6 +72,13 @@ node.setAttribute('action', action) pass + def set_path(self, path): + self.paht = path + node = self.node + path_txt = ' '.join([str(c) for c in path.strip().split()]) + node.setAttribute('path', path_txt) + pass + def reparse(self): condition = node.getAttribute('condition') target = node.getAttribute('target') @@ -79,10 +87,17 @@ except: action = None pass + try: + path = node.getAttribute('path').strip().split() + path = [float(c) for c in path] + except: + path = None + pass self.condition = condition self.target = target self.action = action + self.path = path pass def update_node(self): @@ -92,6 +107,9 @@ if self.action: node.setAttribute('action', self.action) pass + if self.path: + node.setAttribute('path', self.path) + pass pass ## \brief Create a node according status of the object. @@ -136,6 +154,9 @@ name = None entry_action = None transitions = None + r = None + x = 0 + y = 0 def __init__(self, node=None): self.node = node @@ -152,6 +173,18 @@ self.node.setAttribute('entry_action', action) pass + def set_r(self, r): + self.r = r + self.node.setAttribute('r', str(r)) + pass + + def set_xy(self, x, y): + self.x = x + self.y = y + self.node.setAttribute('x', str(x)) + self.node.setAttribute('y', str(y)) + pass + def reparse(self): node = self.node @@ -161,6 +194,21 @@ except: entry_action = None pass + try: + r = float(node.getAttribute('r')) + except: + r = None + pass + try: + x = float(node.getAttribute('x')) + except: + x = 0 + pass + try: + y = float(node.getAttribute('y')) + except: + y = 0 + pass all_transitions = [Transition.parse_transition(child) for child in node.childList() @@ -171,6 +219,9 @@ self.name = name self.transitions = transitions self.entry_action = entry_action + self.r = r + self.x = x + self.y = y pass def update_node(self): @@ -180,6 +231,15 @@ if self.entry_action: node.setAttribute('entry_action', self.entry_action) pass + if self.r: + node.setAttribute('r', self.r) + pass + if self.x: + node.setAttribute('x', self.x) + pass + if self.y: + node.setAttribute('y', self.y) + pass transitions = self.transitions for trn in transitions: @@ -1050,6 +1110,31 @@ state.set_entry_action(entry_action) pass + def set_state_r(self, state_name, r): + state = self._get_state(state_name) + state.set_r(r) + pass + + def set_state_xy(self, state_name, x, y): + state = self._get_state(state_name) + state.set_xy(x, y) + pass + + def get_state_entry_action(self, state_name): + state = self._get_state(state_name) + action = state.get_entry_action() + return action + + def get_state_r(self, state_name): + state = self._get_state(state_name) + r = state.r + return r + + def get_state_xy(self, state_name): + state = self._get_state(state_name) + xy = state.x, state.y + return xy + def all_transitions(self, state_name): state = self._get_state(state_name) trn_names = state.all_transitions() @@ -1077,13 +1162,19 @@ cond = trn.condition target = trn.target action = trn.action + path = trn.path - return cond, target, action + return cond, target, action, path def set_transition_action(self, state_name, cond, action): trn = state.get_transition(state_name, cond) trn.set_action(action) pass + + def set_transition_path(self, state_name, cond, path): + trn = state.get_transition(state_name, cond) + trn.set_path(path) + pass pass diff -r c586981ecf1a -r c1e70540541c pyink/domview_ui.py --- a/pyink/domview_ui.py Mon Apr 18 11:54:10 2011 +0800 +++ b/pyink/domview_ui.py Sun Apr 24 12:30:47 2011 +0800 @@ -543,6 +543,26 @@ self._dom.set_entry_action(state_name, entry_action) pass + def set_state_r(self, state_name, r): + self._dom.set_state_r(state_name, r) + pass + + def set_state_xy(self, state_name, x, y): + self._dom.set_state_xy(state_name, x, y) + pass + + def get_state_entry_action(self, state_name): + action = self._dom.get_state_entry_action(state_name) + return action + + def get_state_r(self, state_name): + r = self._dom.get_state_r(state_name) + return r + + def get_state_xy(self, state_name): + xy = self._dom.get_state_xy(state_name) + return xy + def all_transitions(self, state_name): return self._dom.all_transitions(state_name) @@ -564,6 +584,10 @@ def set_transition_action(self, state_name, cond, action): self._dom.set_transition_action(state_name, cond, action) pass + + def set_transition_path(self, state_name, cond, path): + self._dom.set_transition_path(state_name, cond, path) + pass pass