ソースを参照

Fix many strange problems with TkInter

Yentl Van Tendeloo 8 年 前
コミット
cea5b52d4f
4 ファイル変更209 行追加74 行削除
  1. 65 1
      classes/canvas/canvas.xml
  2. 11 0
      classes/canvas/canvas_element.xml
  3. 114 23
      frontend.py
  4. 19 50
      sccd_widget.py

+ 65 - 1
classes/canvas/canvas.xml

@@ -79,12 +79,22 @@
                         </script>
                     </transition>
 
-                    <transition event="right-click" cond="self.currently_selected is not None" target="../creating_element">
+                    <transition event="right-click" cond="self.currently_selected is not None and id(self) == ID" target="../creating_element">
+                        <parameter name="ID"/>
                         <script>
                             self.create_location = (self.last_x, self.last_y)
                         </script>
                     </transition>
 
+                    <transition event="create_line" target="../creating_line">
+                        <parameter name="cs_element"/>
+                        <parameter name="as_element"/>
+                        <parameter name="coordinates"/>
+                        <script>
+                            self.creating_line = (cs_element, as_element, coordinates)
+                        </script>
+                    </transition>
+
                     <transition event="define_group" target="../creating_group">
                         <parameter name="element"/>
                         <script>
@@ -145,6 +155,60 @@
                     </transition>
                 </state>
 
+                <state id="creating_line" initial="drawing">
+                    <onentry>
+                        <script>
+                            self.tmp_line = self.create_line(self.creating_line[2][0], self.creating_line[2][1], self.last_x, self.last_y)
+                        </script>
+                    </onentry>
+
+                    <onexit>
+                        <script>
+                            self.delete(self.tmp_line)
+                        </script>
+                    </onexit>
+
+                    <state id="drawing">
+                        <transition event="motion" target=".">
+                            <script>
+                                x, y, _, _ = self.coords(self.tmp_line)
+
+                                # NOTE: make sure that you can not click on the temporary line itself
+                                if x > self.last_x:
+                                    self.last_x += 2
+                                else:
+                                    self.last_x -= 2
+
+                                if y > self.last_y:
+                                    self.last_y += 2
+                                else:
+                                    self.last_y -= 2
+
+                                self.coords(self.tmp_line, x, y, self.last_x, self.last_y)
+                                pass
+                            </script>
+                        </transition>
+
+                        <transition event="right-click" cond="ID == id(self)" target="../../ready">
+                            <parameter name="ID"/>
+                            <script>
+                                print("Release on canvas " + str(ID))
+                            </script>
+                        </transition>
+
+                        <transition event="create_line" target="../create_in_mv">
+                            <parameter name="cs_element"/>
+                            <parameter name="as_element"/>
+                            <script>
+                                origin_cs, origin_as, _ = self.creating_line
+                                self.creating_line = (origin_cs, origin_as, cs_element, as_element)
+                            </script>
+                        </transition>
+                    </state>
+
+                    <state id="create_in_mv"/>
+                </state>
+
                 <state id="creating_group">
                     <transition event="instance_created" target="../wait_canvas_element_ready">
                         <parameter name="assoc_name"/>

+ 11 - 0
classes/canvas/canvas_element.xml

@@ -144,6 +144,17 @@
                 <parameter name="ID"/>
             </transition>
 
+            <transition event="right-click" cond="id(self) == ID" target=".">
+                <parameter name="ID"/>
+                <script>
+                    print("Right click in element " + str(self.cs_element))
+                </script>
+                <raise event="create_line" scope="narrow" target="'parent'">
+                    <parameter expr="self.cs_element"/>
+                    <parameter expr="self.as_element"/>
+                    <parameter expr="(self.last_x, self.last_y)"/>
+                </raise>
+            </transition>
         </state>
 
         <state id="dragging">

+ 114 - 23
frontend.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Mon Oct  9 13:35:39 2017
+Date:   Mon Oct  9 15:39:54 2017
 
 Model author: Yentl Van Tendeloo
 Model name:   Modelverse Visual Editor - Tkinter Version 
@@ -7180,24 +7180,35 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         # state /ready/process_events/ready
         self.states["/ready/process_events/ready"] = State(4, "/ready/process_events/ready", self)
         
+        # state /ready/process_events/creating_line
+        self.states["/ready/process_events/creating_line"] = State(5, "/ready/process_events/creating_line", self)
+        self.states["/ready/process_events/creating_line"].setEnter(self._ready_process_events_creating_line_enter)
+        self.states["/ready/process_events/creating_line"].setExit(self._ready_process_events_creating_line_exit)
+        
+        # state /ready/process_events/creating_line/drawing
+        self.states["/ready/process_events/creating_line/drawing"] = State(6, "/ready/process_events/creating_line/drawing", self)
+        
+        # state /ready/process_events/creating_line/create_in_mv
+        self.states["/ready/process_events/creating_line/create_in_mv"] = State(7, "/ready/process_events/creating_line/create_in_mv", self)
+        
         # state /ready/process_events/creating_group
-        self.states["/ready/process_events/creating_group"] = State(5, "/ready/process_events/creating_group", self)
+        self.states["/ready/process_events/creating_group"] = State(8, "/ready/process_events/creating_group", self)
         
         # state /ready/process_events/wait_canvas_element_ready
-        self.states["/ready/process_events/wait_canvas_element_ready"] = State(6, "/ready/process_events/wait_canvas_element_ready", self)
+        self.states["/ready/process_events/wait_canvas_element_ready"] = State(9, "/ready/process_events/wait_canvas_element_ready", self)
         
         # state /ready/process_events/creating_element
-        self.states["/ready/process_events/creating_element"] = State(7, "/ready/process_events/creating_element", self)
+        self.states["/ready/process_events/creating_element"] = State(10, "/ready/process_events/creating_element", self)
         self.states["/ready/process_events/creating_element"].setEnter(self._ready_process_events_creating_element_enter)
         
         # state /ready/process_events/waiting_for_clear
-        self.states["/ready/process_events/waiting_for_clear"] = State(8, "/ready/process_events/waiting_for_clear", self)
+        self.states["/ready/process_events/waiting_for_clear"] = State(11, "/ready/process_events/waiting_for_clear", self)
         
         # state /ready/update_loading
-        self.states["/ready/update_loading"] = State(9, "/ready/update_loading", self)
+        self.states["/ready/update_loading"] = State(12, "/ready/update_loading", self)
         
         # state /ready/update_loading/updating
-        self.states["/ready/update_loading/updating"] = State(10, "/ready/update_loading/updating", self)
+        self.states["/ready/update_loading/updating"] = State(13, "/ready/update_loading/updating", self)
         self.states["/ready/update_loading/updating"].setEnter(self._ready_update_loading_updating_enter)
         self.states["/ready/update_loading/updating"].setExit(self._ready_update_loading_updating_exit)
         
@@ -7207,14 +7218,18 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         self.states["/ready"].addChild(self.states["/ready/process_events"])
         self.states["/ready"].addChild(self.states["/ready/update_loading"])
         self.states["/ready/process_events"].addChild(self.states["/ready/process_events/ready"])
+        self.states["/ready/process_events"].addChild(self.states["/ready/process_events/creating_line"])
         self.states["/ready/process_events"].addChild(self.states["/ready/process_events/creating_group"])
         self.states["/ready/process_events"].addChild(self.states["/ready/process_events/wait_canvas_element_ready"])
         self.states["/ready/process_events"].addChild(self.states["/ready/process_events/creating_element"])
         self.states["/ready/process_events"].addChild(self.states["/ready/process_events/waiting_for_clear"])
+        self.states["/ready/process_events/creating_line"].addChild(self.states["/ready/process_events/creating_line/drawing"])
+        self.states["/ready/process_events/creating_line"].addChild(self.states["/ready/process_events/creating_line/create_in_mv"])
         self.states["/ready/update_loading"].addChild(self.states["/ready/update_loading/updating"])
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/main"]
         self.states["/ready/process_events"].default_state = self.states["/ready/process_events/ready"]
+        self.states["/ready/process_events/creating_line"].default_state = self.states["/ready/process_events/creating_line/drawing"]
         self.states["/ready/update_loading"].default_state = self.states["/ready/update_loading/updating"]
         
         # transition /main
@@ -7237,18 +7252,17 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         _ready_process_events_ready_2.setTrigger(Event("right-click", None))
         _ready_process_events_ready_2.setGuard(self._ready_process_events_ready_2_guard)
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_2)
-        _ready_process_events_ready_3 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/creating_group"]])
+        _ready_process_events_ready_3 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/creating_line"]])
         _ready_process_events_ready_3.setAction(self._ready_process_events_ready_3_exec)
-        _ready_process_events_ready_3.setTrigger(Event("define_group", None))
+        _ready_process_events_ready_3.setTrigger(Event("create_line", None))
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_3)
-        _ready_process_events_ready_4 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/ready"]])
+        _ready_process_events_ready_4 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/creating_group"]])
         _ready_process_events_ready_4.setAction(self._ready_process_events_ready_4_exec)
-        _ready_process_events_ready_4.setTrigger(Event("define_contains", None))
+        _ready_process_events_ready_4.setTrigger(Event("define_group", None))
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_4)
         _ready_process_events_ready_5 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/ready"]])
         _ready_process_events_ready_5.setAction(self._ready_process_events_ready_5_exec)
-        _ready_process_events_ready_5.setTrigger(Event("draw_canvas", None))
-        _ready_process_events_ready_5.setGuard(self._ready_process_events_ready_5_guard)
+        _ready_process_events_ready_5.setTrigger(Event("define_contains", None))
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_5)
         _ready_process_events_ready_6 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/ready"]])
         _ready_process_events_ready_6.setAction(self._ready_process_events_ready_6_exec)
@@ -7257,12 +7271,32 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_6)
         _ready_process_events_ready_7 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/ready"]])
         _ready_process_events_ready_7.setAction(self._ready_process_events_ready_7_exec)
-        _ready_process_events_ready_7.setTrigger(Event("instance_created", None))
+        _ready_process_events_ready_7.setTrigger(Event("draw_canvas", None))
+        _ready_process_events_ready_7.setGuard(self._ready_process_events_ready_7_guard)
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_7)
         _ready_process_events_ready_8 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/ready"]])
         _ready_process_events_ready_8.setAction(self._ready_process_events_ready_8_exec)
-        _ready_process_events_ready_8.setTrigger(Event("moved_group", None))
+        _ready_process_events_ready_8.setTrigger(Event("instance_created", None))
         self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_8)
+        _ready_process_events_ready_9 = Transition(self, self.states["/ready/process_events/ready"], [self.states["/ready/process_events/ready"]])
+        _ready_process_events_ready_9.setAction(self._ready_process_events_ready_9_exec)
+        _ready_process_events_ready_9.setTrigger(Event("moved_group", None))
+        self.states["/ready/process_events/ready"].addTransition(_ready_process_events_ready_9)
+        
+        # transition /ready/process_events/creating_line/drawing
+        _ready_process_events_creating_line_drawing_0 = Transition(self, self.states["/ready/process_events/creating_line/drawing"], [self.states["/ready/process_events/creating_line/drawing"]])
+        _ready_process_events_creating_line_drawing_0.setAction(self._ready_process_events_creating_line_drawing_0_exec)
+        _ready_process_events_creating_line_drawing_0.setTrigger(Event("motion", None))
+        self.states["/ready/process_events/creating_line/drawing"].addTransition(_ready_process_events_creating_line_drawing_0)
+        _ready_process_events_creating_line_drawing_1 = Transition(self, self.states["/ready/process_events/creating_line/drawing"], [self.states["/ready/process_events/ready"]])
+        _ready_process_events_creating_line_drawing_1.setAction(self._ready_process_events_creating_line_drawing_1_exec)
+        _ready_process_events_creating_line_drawing_1.setTrigger(Event("right-click", None))
+        _ready_process_events_creating_line_drawing_1.setGuard(self._ready_process_events_creating_line_drawing_1_guard)
+        self.states["/ready/process_events/creating_line/drawing"].addTransition(_ready_process_events_creating_line_drawing_1)
+        _ready_process_events_creating_line_drawing_2 = Transition(self, self.states["/ready/process_events/creating_line/drawing"], [self.states["/ready/process_events/creating_line/create_in_mv"]])
+        _ready_process_events_creating_line_drawing_2.setAction(self._ready_process_events_creating_line_drawing_2_exec)
+        _ready_process_events_creating_line_drawing_2.setTrigger(Event("create_line", None))
+        self.states["/ready/process_events/creating_line/drawing"].addTransition(_ready_process_events_creating_line_drawing_2)
         
         # transition /ready/process_events/creating_group
         _ready_process_events_creating_group_0 = Transition(self, self.states["/ready/process_events/creating_group"], [self.states["/ready/process_events/wait_canvas_element_ready"]])
@@ -7298,6 +7332,12 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         _ready_update_loading_updating_0.setTrigger(Event("_0after"))
         self.states["/ready/update_loading/updating"].addTransition(_ready_update_loading_updating_0)
     
+    def _ready_process_events_creating_line_enter(self):
+        self.tmp_line = self.create_line(self.creating_line[2][0], self.creating_line[2][1], self.last_x, self.last_y)
+    
+    def _ready_process_events_creating_line_exit(self):
+        self.delete(self.tmp_line)
+    
     def _ready_process_events_creating_element_enter(self):
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['instantiate', [current_model, self.currently_selected, None, '']])]))
         self.elems.append([0, self.create_image(self.last_x, self.last_y, image=self.loading[0])])
@@ -7322,47 +7362,84 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         self.currently_selected = element_name
     
     def _ready_process_events_ready_2_exec(self, parameters):
+        ID = parameters[0]
         self.create_location = (self.last_x, self.last_y)
     
     def _ready_process_events_ready_2_guard(self, parameters):
-        return self.currently_selected is not None
+        ID = parameters[0]
+        return self.currently_selected is not None and id(self) == ID
     
     def _ready_process_events_ready_3_exec(self, parameters):
+        cs_element = parameters[0]
+        as_element = parameters[1]
+        coordinates = parameters[2]
+        self.creating_line = (cs_element, as_element, coordinates)
+    
+    def _ready_process_events_ready_4_exec(self, parameters):
         element = parameters[0]
         self.creating_id = element["id"]
         self.group_location[element['id']] = (element['x'], element['y'])
         self.big_step.outputEventOM(Event("create_instance", None, [self, 'elements', 'CanvasElement', self, (element['x'], element['y']), element['id'], element['__asid']]))
     
-    def _ready_process_events_ready_4_exec(self, parameters):
+    def _ready_process_events_ready_5_exec(self, parameters):
         element = parameters[0]
         self.element_group[element["__target"]] = element["__source"]
     
-    def _ready_process_events_ready_5_exec(self, parameters):
+    def _ready_process_events_ready_6_exec(self, parameters):
         element = parameters[0]
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, self.assoc_links[self.element_group[element['id']]], Event("draw_element", None, [element])]))
     
-    def _ready_process_events_ready_5_guard(self, parameters):
+    def _ready_process_events_ready_6_guard(self, parameters):
         element = parameters[0]
         return element['type'] != 'ConnectingLine'
     
-    def _ready_process_events_ready_6_exec(self, parameters):
+    def _ready_process_events_ready_7_exec(self, parameters):
         element = parameters[0]
         self.big_step.outputEventOM(Event("create_instance", None, [self, 'connecting_lines', 'ConnectingLine', self, element]))
     
-    def _ready_process_events_ready_6_guard(self, parameters):
+    def _ready_process_events_ready_7_guard(self, parameters):
         element = parameters[0]
         return element['type'] == 'ConnectingLine'
     
-    def _ready_process_events_ready_7_exec(self, parameters):
+    def _ready_process_events_ready_8_exec(self, parameters):
         result = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, result]))
     
-    def _ready_process_events_ready_8_exec(self, parameters):
+    def _ready_process_events_ready_9_exec(self, parameters):
         group_element = parameters[0]
         new_location = parameters[1]
         self.group_location[group_element] = new_location
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'connecting_lines', Event("moved_element", None, [group_element, new_location])]))
     
+    def _ready_process_events_creating_line_drawing_0_exec(self, parameters):
+        x, y, _, _ = self.coords(self.tmp_line)
+        if x > self.last_x:
+            self.last_x += 2
+        else:
+            self.last_x -= 2
+        
+        if y > self.last_y:
+            self.last_y += 2
+        else:
+            self.last_y -= 2
+        
+        self.coords(self.tmp_line, x, y, self.last_x, self.last_y)
+        pass
+    
+    def _ready_process_events_creating_line_drawing_1_exec(self, parameters):
+        ID = parameters[0]
+        print("Release on canvas " + str(ID))
+    
+    def _ready_process_events_creating_line_drawing_1_guard(self, parameters):
+        ID = parameters[0]
+        return ID == id(self)
+    
+    def _ready_process_events_creating_line_drawing_2_exec(self, parameters):
+        cs_element = parameters[0]
+        as_element = parameters[1]
+        origin_cs, origin_as, _ = self.creating_line
+        self.creating_line = (origin_cs, origin_as, cs_element, as_element)
+    
     def _ready_process_events_creating_group_0_exec(self, parameters):
         assoc_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, assoc_name]))
@@ -7856,6 +7933,11 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         _main_2.setTrigger(Event("middle-click", None))
         _main_2.setGuard(self._main_2_guard)
         self.states["/main"].addTransition(_main_2)
+        _main_3 = Transition(self, self.states["/main"], [self.states["/main"]])
+        _main_3.setAction(self._main_3_exec)
+        _main_3.setTrigger(Event("right-click", None))
+        _main_3.setGuard(self._main_3_guard)
+        self.states["/main"].addTransition(_main_3)
         
         # transition /dragging
         _dragging_0 = Transition(self, self.states["/dragging"], [self.states["/dragging"]])
@@ -7998,6 +8080,15 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         ID = parameters[0]
         return id(self) == ID
     
+    def _main_3_exec(self, parameters):
+        ID = parameters[0]
+        print("Right click in element " + str(self.cs_element))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("create_line", None, [self.cs_element, self.as_element, (self.last_x, self.last_y)])]))
+    
+    def _main_3_guard(self, parameters):
+        ID = parameters[0]
+        return id(self) == ID
+    
     def _dragging_0_exec(self, parameters):
         ID = parameters[0]
         new_x = self.coordinates[0] + (self.last_x - self.original_coords[0])

+ 19 - 50
sccd_widget.py

@@ -29,7 +29,6 @@ class SCCDWidget:
                 tagorid = [tagorid]
             for t in tagorid:
                 self.bindable.tag_bind(t, "<Button>", self.on_click)
-                self.bindable.tag_bind(t, "<Double-Button>", self.on_dbclick)
                 self.bindable.tag_bind(t, "<ButtonRelease>", self.on_release)
                 self.bindable.tag_bind(t, "<Motion>", self.on_motion)
                 self.bindable.tag_bind(t, "<Enter>", self.on_enter)
@@ -44,61 +43,23 @@ class SCCDWidget:
             self.bindable.bind("<Leave>", self.on_leave)
             self.bindable.bind("<Key>", self.on_key)
             self.bindable.bind("<KeyRelease>", self.on_key_release)
-            self.bindable.bind("<Shift-Up>",self.zoom_in)
-            self.bindable.bind("<Shift-Down>", self.zoom_out)
-            self.bindable.bind("<MouseWheel>", self.scroller)
 
         self.last_x = 50
         self.last_y = 50
-        self.event_delta = 0
-        self.zoomer_count = 0
         self.selected_type = None
 
-    def scroller(self, event):
-        self.event_delta = event.delta
-        event_name= "scroll_mousewheel"
-        self.last_x = event.x
-        self.last_y = event.y
-        SCCDWidget.controller.addInput(Event(event_name, "input", [id(self)]))
-        return "break"
-
-    def zoom_in(self, event):
-        event_name = "zoomer_event"
-        self.last_x = event.x
-        self.last_y = event.y
-        if self.zoomer_count <=6:
-            self.event_delta = 120
-            self.zoomer_count +=1
-        SCCDWidget.controller.addInput(Event(event_name, "input", [id(self)]))
-        return "break"
-
-    def zoom_out(self, event):
-        event_name = "zoomer_event"
-        self.last_x = event.x
-        self.last_y = event.y
-        if self.zoomer_count >=-6:
-            self.event_delta = -120
-            self.zoomer_count -=1
-        SCCDWidget.controller.addInput(Event(event_name, "input", [id(self)]))
-        return "break"
-
-    def on_dbclick(self, event):
-        event_name = None
-
-        if event.num == 1:
-            event_name = "left-dbclick"
-        elif event.num == 2:
-            event_name = "middle-dbclick"
-        elif event.num == 3:
-            event_name = "right-dbclick"
-
-        if event_name:
-            self.last_x = event.x
-            self.last_y = event.y
-            SCCDWidget.controller.addInput(Event(event_name, "input", [id(self)]))
-        return "break"
-
     def on_click(self, event):
+        ''' Prevent event propagation from canvas elements to canvas... '''
+        if isinstance(self.bindable, tk.Canvas) and self.mytagorid is None:
+            print("Click on canvas")
+            if hasattr(event.widget, 'clicked'):
+                if event.widget.clicked:
+                    event.widget.clicked = False
+                    return
+        else:
+            print("Click on not canvas")
+            event.widget.clicked = True
+
         event_name = None
         if event.num == 1:
             event_name = "left-click"
@@ -114,6 +75,14 @@ class SCCDWidget:
         return "break"
 
     def on_release(self, event):
+        if isinstance(self.bindable, tk.Canvas) and self.mytagorid is None:
+            if hasattr(event.widget, 'clicked'):
+                if event.widget.clicked:
+                    event.widget.clicked = False
+                    return
+        else:
+            event.widget.clicked = True
+
         event_name = None
 
         if event.num == 1: