changeset 1469:c1e70540541c

Drawing functions for states and transitions
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 24 Apr 2011 12:30:47 +0800
parents c586981ecf1a
children 2a9b9c281f80
files pyink/FSM_window.py pyink/domview.py pyink/domview_ui.py
diffstat 3 files changed, 253 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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
 
--- 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
 
 
--- 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