فهرست منبع

Support changing attributes and many more operations (but crashes...)

Yentl Van Tendeloo 8 سال پیش
والد
کامیت
ebb45f060d
8فایلهای تغییر یافته به همراه299 افزوده شده و 41 حذف شده
  1. 2 1
      classes/canvas/canvas.xml
  2. 107 6
      classes/canvas/canvas_element.xml
  3. 1 1
      classes/modelverse/modelverse.xml
  4. 0 1
      classes/window/main_window.xml
  5. 151 18
      frontend.py
  6. 1 1
      frontend.xml
  7. 3 1
      models/MM_render.mvc
  8. 34 12
      models/render_SCD.alc

+ 2 - 1
classes/canvas/canvas.xml

@@ -67,6 +67,7 @@
                     <parameter expr="self"/>
                     <parameter expr="(element['x'], element['y'])"/>
                     <parameter expr="element['id']"/>
+                    <parameter expr="element['__asid']"/>
                 </raise>
             </transition>
 
@@ -95,7 +96,7 @@
                     self.connecting_lines.setdefault(element['__source'], []).append(element)
                     self.connecting_lines.setdefault(element['__target'], []).append(element)
 
-                    line = self.create_line(source_x, source_y, target_x, target_y)
+                    line = self.create_line(source_x, source_y, target_x, target_y, fill=element['lineColour'], width=element['lineWidth'], arrow=tk.LAST if element['arrow'] else tk.NONE)
                     element['elem'] = line
                 </script>
             </transition>

+ 107 - 6
classes/canvas/canvas_element.xml

@@ -3,11 +3,13 @@
         <association name="parent" class="A" min="1" max="1" />
         <inheritance class="SCCDWidget" priority='0'/>
         <association name="elements" class="CanvasElement"/>
+        <association name="prompt" class="PromptWindow"/>
     </relationships>
     <constructor>
         <parameter name="parent"/>
         <parameter name="coordinates"/>
-        <parameter name="group_element"/>
+        <parameter name="cs_element"/>
+        <parameter name="as_element"/>
         <super class="SCCDWidget">
             <parameter expr="True"/>
         </super>
@@ -16,7 +18,9 @@
             self.coordinates = coordinates
             self.elements = {}
             self.tmp = {}
-            self.group_element = group_element
+            self.cs_element = cs_element
+            self.as_element = as_element
+            self.diff_results = {}
         </body>
     </constructor>
     <destructor>
@@ -55,6 +59,10 @@
                     self.prev_y = self.last_y
                 </script>
             </transition>
+
+            <transition event="middle-click" cond="id(self) == ID" target="../update_attrs">
+                <parameter name="ID"/>
+            </transition>
         </state>
 
         <state id="dragging">
@@ -83,7 +91,7 @@
                     delta_y = self.original_coords[1] - self.last_y
                 </script>
                 <raise event="moved_group" scope="narrow" target="'parent'">
-                    <parameter expr="self.group_element"/>
+                    <parameter expr="self.cs_element"/>
                     <parameter expr="(self.coordinates[0] - delta_x, self.coordinates[1] - delta_y)"/>
                 </raise>
             </transition>
@@ -99,12 +107,105 @@
             </transition>
         </state>
 
-        <state id="update_mv" initial="x">
+        <state id="update_attrs" initial="query">
+            <state id="query">
+                <onentry>
+                    <raise event="mv_request" scope="broad">
+                        <parameter expr="'read_attrs'"/>
+                        <parameter expr="[current_model, self.as_element]"/>
+                    </raise>
+                </onentry>
+
+                <transition event="mv_response" target="../prompt">
+                    <parameter name="result"/>
+                    <script>
+                        self.prev_results = result
+                    </script>
+                </transition>
+            </state>
+
+            <state id="prompt">
+                <onentry>
+                    <raise event="create_instance" scope="cd">
+                        <parameter expr="'prompt'"/>
+                        <parameter expr="'PromptWindow'"/>
+                        <parameter expr="self.prev_results"/>
+                        <parameter expr="{}"/>
+                    </raise>
+                </onentry>
+
+                <transition event="instance_created" target="../wait_for_results">
+                    <parameter name="name"/>
+                    <raise event="start_instance" scope="cd">
+                        <parameter expr="name"/>
+                    </raise>
+                </transition>
+            </state>
+
+            <state id="wait_for_results">
+                <transition event="prompt_results" target=".">
+                    <parameter name="results"/>
+                    <script>
+                        for k in results:
+                            if results[k] != self.prev_results[k]:
+                                self.diff_results[k] = json.loads(results[k])
+                        self.remaining_responses = len(self.diff_results)
+                    </script>
+                </transition>
+
+                <transition event="close_window" target="../process_results">
+                    <raise event="delete_instance" scope="cd">
+                        <parameter expr="'prompt'"/>
+                    </raise>
+                </transition>
+            </state>
+
+            <state id="process_results">
+                <transition cond="len(self.diff_results) > 0" target=".">
+                    <script>
+                        k, v = self.diff_results.popitem()
+                    </script>
+                    <raise event="mv_request" scope="broad">
+                        <parameter expr="'attr_assign'"/>
+                        <parameter expr="[current_model, self.as_element, k, v]"/>
+                    </raise>
+                </transition>
+                <transition cond="self.remaining_responses == 0" target="../mark_dirty"/>
+                <transition event="mv_response" target=".">
+                    <script>
+                        self.remaining_responses -= 1
+                    </script>
+                </transition>
+            </state>
+
+            <state id="mark_dirty">
+                <onentry>
+                    <raise event="mv_request" scope="broad">
+                        <parameter expr="'attr_assign'"/>
+                        <parameter expr="[current_rendered_model, self.cs_element, 'dirty', True]"/>
+                    </raise>
+                </onentry>
+                <transition target="../../main"/>
+            </state>
+        </state>
+
+        <state id="update_mv" initial="mark_dirty">
+            <state id="mark_dirty">
+                <onentry>
+                    <raise event="mv_request" scope="broad">
+                        <parameter expr="'attr_assign'"/>
+                        <parameter expr="[current_rendered_model, self.cs_element, 'dirty', True]"/>
+                    </raise>
+                </onentry>
+
+                <transition event="mv_response" target="../x"/>
+            </state>
+
             <state id="x">
                 <onentry>
                     <raise event="mv_request" scope="broad">
                         <parameter expr="'attr_assign'"/>
-                        <parameter expr="[current_rendered_model, self.group_element, 'x', self.coordinates[0]]"/>
+                        <parameter expr="[current_rendered_model, self.cs_element, 'x', self.coordinates[0]]"/>
                     </raise>
                 </onentry>
 
@@ -115,7 +216,7 @@
                 <onentry>
                     <raise event="mv_request" scope="broad">
                         <parameter expr="'attr_assign'"/>
-                        <parameter expr="[current_rendered_model, self.group_element, 'y', self.coordinates[1]]"/>
+                        <parameter expr="[current_rendered_model, self.cs_element, 'y', self.coordinates[1]]"/>
                     </raise>
                 </onentry>
 

+ 1 - 1
classes/modelverse/modelverse.xml

@@ -1132,7 +1132,7 @@
                             <script>
                                 response = self.responses.pop(0).strip()
                                 _, response = response.split(": ", 1)
-                                values = {line.split(": ", 1)[0]: line.split(": ", 1)[1] for line in response.split("\n")}
+                                values = {line.split(" : ", 1)[0]: line.split(" : ", 1)[1] for line in response.split("\n")}
                                 values = {key: values[key].split(" = ", 1)[1] for key in values}
                             </script>
                             <raise event="result">

+ 0 - 1
classes/window/main_window.xml

@@ -424,7 +424,6 @@
                     <transition event="mv_response" target="../render_model">
                         <parameter name="result"/>
                         <script>
-                            print("Result: " + str(result))
                             self.rendered = result
                         </script>
                     </transition>

+ 151 - 18
frontend.py

@@ -1,9 +1,9 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Fri Sep 15 11:45:03 2017
+Date:   Wed Sep 27 15:50:59 2017
 
-Model author: Yentl Van Tendeloo and Addis Gebremichael
+Model author: Yentl Van Tendeloo
 Model name:   Modelverse Visual Editor - Tkinter Version 
 Model description:
 Modelverse Visual Editor
@@ -3027,7 +3027,7 @@ class Modelverse(RuntimeClassBase):
     def _initialized_behaviour_operations_read_attrs_0_exec(self, parameters):
         response = self.responses.pop(0).strip()
         _, response = response.split(": ", 1)
-        values = {line.split(": ", 1)[0]: line.split(": ", 1)[1] for line in response.split("\n")}
+        values = {line.split(" : ", 1)[0]: line.split(" : ", 1)[1] for line in response.split("\n")}
         values = {key: values[key].split(" = ", 1)[1] for key in values}
         self.raiseInternalEvent(Event("result", None, [values]))
     
@@ -4474,7 +4474,6 @@ class MainWindow(RuntimeClassBase, tk.Toplevel, SCCDWidget):
     
     def _running_rerender_model_request_render_0_exec(self, parameters):
         result = parameters[0]
-        print("Result: " + str(result))
         self.rendered = result
     
     def _running_rerender_model_render_model_allocate_groups_0_exec(self, parameters):
@@ -5735,7 +5734,7 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         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']]))
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'elements', 'CanvasElement', self, (element['x'], element['y']), element['id'], element['__asid']]))
     
     def _ready_2_exec(self, parameters):
         element = parameters[0]
@@ -5759,7 +5758,7 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         self.connecting_lines.setdefault(element['__source'], []).append(element)
         self.connecting_lines.setdefault(element['__target'], []).append(element)
         
-        line = self.create_line(source_x, source_y, target_x, target_y)
+        line = self.create_line(source_x, source_y, target_x, target_y, fill=element['lineColour'], width=element['lineWidth'], arrow=tk.LAST if element['arrow'] else tk.NONE)
         element['elem'] = line
     
     def _ready_4_guard(self, parameters):
@@ -5800,7 +5799,7 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         RuntimeClassBase.initializeStatechart(self)
 
 class CanvasElement(RuntimeClassBase, SCCDWidget):
-    def __init__(self, controller, parent, coordinates, group_element):
+    def __init__(self, controller, parent, coordinates, cs_element, as_element):
         RuntimeClassBase.__init__(self, controller)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
@@ -5813,15 +5812,17 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         self.build_statechart_structure()
         
         # call user defined constructor
-        CanvasElement.user_defined_constructor(self, parent, coordinates, group_element)
+        CanvasElement.user_defined_constructor(self, parent, coordinates, cs_element, as_element)
     
-    def user_defined_constructor(self, parent, coordinates, group_element):
+    def user_defined_constructor(self, parent, coordinates, cs_element, as_element):
         SCCDWidget.__init__(self, True)
         self.containing_canvas = parent
         self.coordinates = coordinates
         self.elements = {}
         self.tmp = {}
-        self.group_element = group_element
+        self.cs_element = cs_element
+        self.as_element = as_element
+        self.diff_results = {}
     
     def user_defined_destructor(self):
         # call super class destructors
@@ -5841,26 +5842,59 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         # state /dragging
         self.states["/dragging"] = State(2, "/dragging", self)
         
+        # state /update_attrs
+        self.states["/update_attrs"] = State(3, "/update_attrs", self)
+        
+        # state /update_attrs/query
+        self.states["/update_attrs/query"] = State(4, "/update_attrs/query", self)
+        self.states["/update_attrs/query"].setEnter(self._update_attrs_query_enter)
+        
+        # state /update_attrs/prompt
+        self.states["/update_attrs/prompt"] = State(5, "/update_attrs/prompt", self)
+        self.states["/update_attrs/prompt"].setEnter(self._update_attrs_prompt_enter)
+        
+        # state /update_attrs/wait_for_results
+        self.states["/update_attrs/wait_for_results"] = State(6, "/update_attrs/wait_for_results", self)
+        
+        # state /update_attrs/process_results
+        self.states["/update_attrs/process_results"] = State(7, "/update_attrs/process_results", self)
+        
+        # state /update_attrs/mark_dirty
+        self.states["/update_attrs/mark_dirty"] = State(8, "/update_attrs/mark_dirty", self)
+        self.states["/update_attrs/mark_dirty"].setEnter(self._update_attrs_mark_dirty_enter)
+        
         # state /update_mv
-        self.states["/update_mv"] = State(3, "/update_mv", self)
+        self.states["/update_mv"] = State(9, "/update_mv", self)
+        
+        # state /update_mv/mark_dirty
+        self.states["/update_mv/mark_dirty"] = State(10, "/update_mv/mark_dirty", self)
+        self.states["/update_mv/mark_dirty"].setEnter(self._update_mv_mark_dirty_enter)
         
         # state /update_mv/x
-        self.states["/update_mv/x"] = State(4, "/update_mv/x", self)
+        self.states["/update_mv/x"] = State(11, "/update_mv/x", self)
         self.states["/update_mv/x"].setEnter(self._update_mv_x_enter)
         
         # state /update_mv/y
-        self.states["/update_mv/y"] = State(5, "/update_mv/y", self)
+        self.states["/update_mv/y"] = State(12, "/update_mv/y", self)
         self.states["/update_mv/y"].setEnter(self._update_mv_y_enter)
         
         # add children
         self.states[""].addChild(self.states["/main"])
         self.states[""].addChild(self.states["/dragging"])
+        self.states[""].addChild(self.states["/update_attrs"])
         self.states[""].addChild(self.states["/update_mv"])
+        self.states["/update_attrs"].addChild(self.states["/update_attrs/query"])
+        self.states["/update_attrs"].addChild(self.states["/update_attrs/prompt"])
+        self.states["/update_attrs"].addChild(self.states["/update_attrs/wait_for_results"])
+        self.states["/update_attrs"].addChild(self.states["/update_attrs/process_results"])
+        self.states["/update_attrs"].addChild(self.states["/update_attrs/mark_dirty"])
+        self.states["/update_mv"].addChild(self.states["/update_mv/mark_dirty"])
         self.states["/update_mv"].addChild(self.states["/update_mv/x"])
         self.states["/update_mv"].addChild(self.states["/update_mv/y"])
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/main"]
-        self.states["/update_mv"].default_state = self.states["/update_mv/x"]
+        self.states["/update_attrs"].default_state = self.states["/update_attrs/query"]
+        self.states["/update_mv"].default_state = self.states["/update_mv/mark_dirty"]
         
         # transition /main
         _main_0 = Transition(self, self.states["/main"], [self.states["/main"]])
@@ -5872,6 +5906,10 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         _main_1.setTrigger(Event("left-click", None))
         _main_1.setGuard(self._main_1_guard)
         self.states["/main"].addTransition(_main_1)
+        _main_2 = Transition(self, self.states["/main"], [self.states["/update_attrs"]])
+        _main_2.setTrigger(Event("middle-click", None))
+        _main_2.setGuard(self._main_2_guard)
+        self.states["/main"].addTransition(_main_2)
         
         # transition /dragging
         _dragging_0 = Transition(self, self.states["/dragging"], [self.states["/dragging"]])
@@ -5885,6 +5923,53 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         _dragging_1.setGuard(self._dragging_1_guard)
         self.states["/dragging"].addTransition(_dragging_1)
         
+        # transition /update_attrs/query
+        _update_attrs_query_0 = Transition(self, self.states["/update_attrs/query"], [self.states["/update_attrs/prompt"]])
+        _update_attrs_query_0.setAction(self._update_attrs_query_0_exec)
+        _update_attrs_query_0.setTrigger(Event("mv_response", None))
+        self.states["/update_attrs/query"].addTransition(_update_attrs_query_0)
+        
+        # transition /update_attrs/prompt
+        _update_attrs_prompt_0 = Transition(self, self.states["/update_attrs/prompt"], [self.states["/update_attrs/wait_for_results"]])
+        _update_attrs_prompt_0.setAction(self._update_attrs_prompt_0_exec)
+        _update_attrs_prompt_0.setTrigger(Event("instance_created", None))
+        self.states["/update_attrs/prompt"].addTransition(_update_attrs_prompt_0)
+        
+        # transition /update_attrs/wait_for_results
+        _update_attrs_wait_for_results_0 = Transition(self, self.states["/update_attrs/wait_for_results"], [self.states["/update_attrs/wait_for_results"]])
+        _update_attrs_wait_for_results_0.setAction(self._update_attrs_wait_for_results_0_exec)
+        _update_attrs_wait_for_results_0.setTrigger(Event("prompt_results", None))
+        self.states["/update_attrs/wait_for_results"].addTransition(_update_attrs_wait_for_results_0)
+        _update_attrs_wait_for_results_1 = Transition(self, self.states["/update_attrs/wait_for_results"], [self.states["/update_attrs/process_results"]])
+        _update_attrs_wait_for_results_1.setAction(self._update_attrs_wait_for_results_1_exec)
+        _update_attrs_wait_for_results_1.setTrigger(Event("close_window", None))
+        self.states["/update_attrs/wait_for_results"].addTransition(_update_attrs_wait_for_results_1)
+        
+        # transition /update_attrs/process_results
+        _update_attrs_process_results_0 = Transition(self, self.states["/update_attrs/process_results"], [self.states["/update_attrs/process_results"]])
+        _update_attrs_process_results_0.setAction(self._update_attrs_process_results_0_exec)
+        _update_attrs_process_results_0.setTrigger(None)
+        _update_attrs_process_results_0.setGuard(self._update_attrs_process_results_0_guard)
+        self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_0)
+        _update_attrs_process_results_1 = Transition(self, self.states["/update_attrs/process_results"], [self.states["/update_attrs/mark_dirty"]])
+        _update_attrs_process_results_1.setTrigger(None)
+        _update_attrs_process_results_1.setGuard(self._update_attrs_process_results_1_guard)
+        self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_1)
+        _update_attrs_process_results_2 = Transition(self, self.states["/update_attrs/process_results"], [self.states["/update_attrs/process_results"]])
+        _update_attrs_process_results_2.setAction(self._update_attrs_process_results_2_exec)
+        _update_attrs_process_results_2.setTrigger(Event("mv_response", None))
+        self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_2)
+        
+        # transition /update_attrs/mark_dirty
+        _update_attrs_mark_dirty_0 = Transition(self, self.states["/update_attrs/mark_dirty"], [self.states["/main"]])
+        _update_attrs_mark_dirty_0.setTrigger(None)
+        self.states["/update_attrs/mark_dirty"].addTransition(_update_attrs_mark_dirty_0)
+        
+        # transition /update_mv/mark_dirty
+        _update_mv_mark_dirty_0 = Transition(self, self.states["/update_mv/mark_dirty"], [self.states["/update_mv/x"]])
+        _update_mv_mark_dirty_0.setTrigger(Event("mv_response", None))
+        self.states["/update_mv/mark_dirty"].addTransition(_update_mv_mark_dirty_0)
+        
         # transition /update_mv/x
         _update_mv_x_0 = Transition(self, self.states["/update_mv/x"], [self.states["/update_mv/y"]])
         _update_mv_x_0.setTrigger(Event("mv_response", None))
@@ -5895,11 +5980,23 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         _update_mv_y_0.setTrigger(Event("mv_response", None))
         self.states["/update_mv/y"].addTransition(_update_mv_y_0)
     
+    def _update_attrs_query_enter(self):
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['read_attrs', [current_model, self.as_element]])]))
+    
+    def _update_attrs_prompt_enter(self):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'prompt', 'PromptWindow', self.prev_results, {}]))
+    
+    def _update_attrs_mark_dirty_enter(self):
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_rendered_model, self.cs_element, 'dirty', True]])]))
+    
+    def _update_mv_mark_dirty_enter(self):
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_rendered_model, self.cs_element, 'dirty', True]])]))
+    
     def _update_mv_x_enter(self):
-        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_rendered_model, self.group_element, 'x', self.coordinates[0]]])]))
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_rendered_model, self.cs_element, 'x', self.coordinates[0]]])]))
     
     def _update_mv_y_enter(self):
-        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_rendered_model, self.group_element, 'y', self.coordinates[1]]])]))
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_rendered_model, self.cs_element, 'y', self.coordinates[1]]])]))
     
     def _main_0_exec(self, parameters):
         element = parameters[0]
@@ -5929,6 +6026,10 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         ID = parameters[0]
         return id(self) == ID
     
+    def _main_2_guard(self, parameters):
+        ID = parameters[0]
+        return id(self) == ID
+    
     def _dragging_0_exec(self, parameters):
         ID = parameters[0]
         delta_x = self.prev_x - self.last_x
@@ -5951,7 +6052,7 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         
         delta_x = self.original_coords[0] - self.last_x
         delta_y = self.original_coords[1] - self.last_y
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("moved_group", None, [self.group_element, (self.coordinates[0] - delta_x, self.coordinates[1] - delta_y)])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("moved_group", None, [self.cs_element, (self.coordinates[0] - delta_x, self.coordinates[1] - delta_y)])]))
     
     def _dragging_0_guard(self, parameters):
         ID = parameters[0]
@@ -5968,6 +6069,37 @@ class CanvasElement(RuntimeClassBase, SCCDWidget):
         ID = parameters[0]
         return id(self) == ID
     
+    def _update_attrs_query_0_exec(self, parameters):
+        result = parameters[0]
+        self.prev_results = result
+    
+    def _update_attrs_prompt_0_exec(self, parameters):
+        name = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, name]))
+    
+    def _update_attrs_wait_for_results_0_exec(self, parameters):
+        results = parameters[0]
+        for k in results:
+            if results[k] != self.prev_results[k]:
+                self.diff_results[k] = json.loads(results[k])
+        self.remaining_responses = len(self.diff_results)
+    
+    def _update_attrs_wait_for_results_1_exec(self, parameters):
+        self.big_step.outputEventOM(Event("delete_instance", None, [self, 'prompt']))
+    
+    def _update_attrs_process_results_0_exec(self, parameters):
+        k, v = self.diff_results.popitem()
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['attr_assign', [current_model, self.as_element, k, v]])]))
+    
+    def _update_attrs_process_results_0_guard(self, parameters):
+        return len(self.diff_results) > 0
+    
+    def _update_attrs_process_results_1_guard(self, parameters):
+        return self.remaining_responses == 0
+    
+    def _update_attrs_process_results_2_exec(self, parameters):
+        self.remaining_responses -= 1
+    
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/main"].getEffectiveTargetStates()
@@ -6038,10 +6170,11 @@ class ObjectManager(ObjectManagerBase):
             instance.associations["parent"] = Association("A", 1, 1)
             instance.associations["elements"] = Association("CanvasElement", 0, -1)
         elif class_name == "CanvasElement":
-            instance = CanvasElement(self.controller, construct_params[0], construct_params[1], construct_params[2])
+            instance = CanvasElement(self.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3])
             instance.associations = {}
             instance.associations["parent"] = Association("A", 1, 1)
             instance.associations["elements"] = Association("CanvasElement", 0, -1)
+            instance.associations["prompt"] = Association("PromptWindow", 0, -1)
         else:
             raise Exception("Cannot instantiate class " + class_name)
         return instance

+ 1 - 1
frontend.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" ?>
-<diagram author="Yentl Van Tendeloo and Addis Gebremichael" name="Modelverse Visual Editor - Tkinter Version ">
+<diagram author="Yentl Van Tendeloo" name="Modelverse Visual Editor - Tkinter Version ">
     <description>
         Modelverse Visual Editor
     </description>

+ 3 - 1
models/MM_render.mvc

@@ -7,10 +7,11 @@ SimpleAttribute Boolean {}
 Class GraphicalElement {
     x : Natural
     y : Natural
-    __asid? : String
 }
 
 Class Group : GraphicalElement {
+    __asid : String
+    dirty : Boolean
 }
 
 Association ConnectingLine (Group, Group) {
@@ -21,6 +22,7 @@ Association ConnectingLine (Group, Group) {
     lineWidth : Natural
     lineColour : String
     arrow : Boolean
+    __asid : String
 }
 
 Class LineElement : GraphicalElement {

+ 34 - 12
models/render_SCD.alc

@@ -14,11 +14,6 @@ Boolean function main(model : Element):
 	Integer text_loc
 	loc = 10
 
-	Element locations_x
-	Element locations_y
-	locations_x = dict_create()
-	locations_y = dict_create()
-
 	Element groups
 	groups = dict_create()
 
@@ -26,10 +21,39 @@ Boolean function main(model : Element):
 	while (set_len(elements) > 0):
 		class = set_pop(elements)
 		
+		// Check if there is already an associated element
 		if (set_len(allOutgoingAssociationInstances(model, class, "TracabilityClass")) > 0):
-			log("Skip draw of class")
-			continue!
-		log("Drawing class")
+			// Yes, but is it still clean?
+			Element related_groups
+			Boolean dirty
+			dirty = False
+
+			related_groups = allAssociationDestinations(model, class, "TracabilityClass")
+			while (set_len(related_groups) > 0):
+				group = set_pop(related_groups)
+				if (value_eq(read_attribute(model, group, "dirty"), True)):
+					// No, so mark all as dirty
+					dirty = True
+					break!
+				else:
+					// Yes, so just ignore this!
+					continue!
+
+			if (bool_not(dirty)):
+				continue!
+			else:
+				related_groups = allAssociationDestinations(model, class, "TracabilityClass")
+				Element to_remove
+				String elem_to_remove
+				while (set_len(related_groups) > 0):
+					group = set_pop(related_groups)
+					to_remove = allAssociationDestinations(model, group, "rendered/contains")
+					while (set_len(to_remove) > 0):
+						elem_to_remove = set_pop(to_remove)
+						if (read_type(model, elem_to_remove) == "rendered/Group"):
+							set_add(to_remove, elem_to_remove)
+						else:
+							model_delete_element(model, to_remove)
 
 		attr_keys = dict_keys(getAttributeList(model, class))
 		text_loc = 5
@@ -37,8 +61,7 @@ Boolean function main(model : Element):
 		group = instantiate_node(model, "rendered/Group", "")
 		instantiate_attribute(model, group, "x", loc)
 		instantiate_attribute(model, group, "y", 10)
-		dict_add(locations_x, class, loc)
-		dict_add(locations_y, class, 10)
+		instantiate_attribute(model, group, "__asid", list_read(string_split(class, "/"), 1))
 		dict_add(groups, class, group)
 		loc = loc + 200
 
@@ -103,9 +126,7 @@ Boolean function main(model : Element):
 		class = set_pop(elements)
 
 		if (set_len(allOutgoingAssociationInstances(model, class, "TracabilityAssociation")) > 0):
-			log("Skip draw of association")
 			continue!
-		log("Drawing association for " + class)
 
 		attr_keys = dict_keys(getAttributeList(model, class))
 
@@ -117,6 +138,7 @@ Boolean function main(model : Element):
 		instantiate_attribute(model, elem, "lineWidth", 1)
 		instantiate_attribute(model, elem, "lineColour", "black")
 		instantiate_attribute(model, elem, "arrow", True)
+		instantiate_attribute(model, elem, "__asid", list_read(string_split(class, "/"), 1))
 		instantiate_link(model, "rendered/contains", "", group, elem)
 
 		instantiate_link(model, "TracabilityAssociation", "", class, elem)