浏览代码

Fixes to connecting lines

Yentl Van Tendeloo 8 年之前
父节点
当前提交
102ee7084f
共有 3 个文件被更改,包括 288 次插入71 次删除
  1. 2 31
      classes/canvas/canvas.xml
  2. 18 11
      classes/canvas/connecting_line.xml
  3. 268 29
      frontend.py

+ 2 - 31
classes/canvas/canvas.xml

@@ -38,35 +38,6 @@
         </body>
     </destructor>
 
-    <method name="move_element">
-        <parameter name="group_element"/>
-        <parameter name="new_location"/>
-        <body>
-            self.group_location[group_element] = new_location
-            if group_element in self.connecting_lines:
-                lines_to_move = self.connecting_lines[group_element]
-
-                for line_element in lines_to_move:
-                    source_x, source_y, _, _ = self.coords(line_element['elem'][0])
-                    _, _, target_x, target_y = self.coords(line_element['elem'][1])
-
-                    if line_element['__source'] == group_element:
-                        # Moved source
-                        source_x = self.group_location[group_element][0] + line_element['offsetSourceX']
-                        source_y = self.group_location[group_element][1] + line_element['offsetSourceY']
-                    if line_element['__target'] == group_element:
-                        # Moved target
-                        target_x = self.group_location[group_element][0] + line_element['offsetTargetX']
-                        target_y = self.group_location[group_element][1] + line_element['offsetTargetY']
-
-                    middle_x = (source_x + target_x) / 2
-                    middle_y = (source_y + target_y) / 2
-
-                    self.coords(line_element['elem'][0], source_x, source_y, middle_x, middle_y)
-                    self.coords(line_element['elem'][1], middle_x, middle_y, target_x, target_y)
-                    self.move_element(line_element['id'], (middle_x, middle_y))
-        </body>
-    </method>
     <scxml initial="main">
         <state id="main">
             <transition target="../ready">
@@ -143,8 +114,8 @@
                     self.group_location[group_element] = new_location
                 </script>
                 <raise event="moved_element" scope="narrow" target="'connecting_lines'">
-                    <parameter expr="'group_element'"/>
-                    <parameter expr="'new_location'"/>
+                    <parameter expr="group_element"/>
+                    <parameter expr="new_location"/>
                 </raise>
             </transition>
         </state>

+ 18 - 11
classes/canvas/connecting_line.xml

@@ -30,21 +30,25 @@
         <state id="init">
             <transition target="../main">
                 <script>
+                    print("Draw connecting line %s from %s to %s" % (self.cs_element['id'], self.cs_element['__source'], self.cs_element['__target']))
                     source_x = self.containing_canvas.group_location[self.cs_element['__source']][0] + self.cs_element['offsetSourceX']
                     source_y = self.containing_canvas.group_location[self.cs_element['__source']][1] + self.cs_element['offsetSourceY']
                     target_x = self.containing_canvas.group_location[self.cs_element['__target']][0] + self.cs_element['offsetTargetX']
                     target_y = self.containing_canvas.group_location[self.cs_element['__target']][1] + self.cs_element['offsetTargetY']
                     middle_x = (source_x + target_x) / 2
                     middle_y = (source_y + target_y) / 2
+
                     self.containing_canvas.group_location[self.cs_element['id']] = (middle_x, middle_y)
 
-                    print("DRAW connecting line from ((%s, %s) to (%s, %s))" % (source_x, source_y, target_x, target_y))
-                    line1 = self.create_line(source_x, source_y, middle_x, middle_y, fill=self.cs_element['lineColour'], width=self.cs_element['lineWidth'], arrow=tk.LAST if self.cs_element['arrow'] else tk.NONE)
-                    line2 = self.create_line(middle_x, middle_y, target_x, target_y, fill=self.cs_element['lineColour'], width=self.cs_element['lineWidth'])
+                    line1 = self.containing_canvas.create_line(source_x, source_y, middle_x, middle_y, fill=self.cs_element['lineColour'], width=self.cs_element['lineWidth'], arrow=tk.LAST if self.cs_element['arrow'] else tk.NONE)
+                    line2 = self.containing_canvas.create_line(middle_x, middle_y, target_x, target_y, fill=self.cs_element['lineColour'], width=self.cs_element['lineWidth'])
                     self.cs_element['elem'] = (line1, line2)
                     self.elements.add(line1)
                     self.elements.add(line2)
 
+                    self.containing_canvas.lower(line1)
+                    self.containing_canvas.lower(line2)
+
                     self.set_bindable_and_tagorid(self.containing_canvas, line1)
                     self.set_bindable_and_tagorid(self.containing_canvas, line2)
                 </script>
@@ -60,28 +64,31 @@
                 <parameter name="element"/>
                 <parameter name="new_location"/>
                 <script>
-                    source_x, source_y, _, _ = self.coords(self.cs_element['elem'][0])
-                    _, _, target_x, target_y = self.coords(self.cs_element['elem'][1])
+                    print("Moving line %s with source %s and target %s" % (self.cs_element['id'], self.cs_element['__source'], self.cs_element['__target']))
+                    source_x, source_y, _, _ = self.containing_canvas.coords(self.cs_element['elem'][0])
+                    _, _, target_x, target_y = self.containing_canvas.coords(self.cs_element['elem'][1])
 
                     if element == self.cs_element['__source']:
                         # Changed source of our link
                         source_x = new_location[0] + self.cs_element['offsetSourceX']
                         source_y = new_location[1] + self.cs_element['offsetSourceY']
+                        print("Move source of line " + self.cs_element['id'])
 
                     if element == self.cs_element['__target']:
                         # Changed target of our link
-                        source_x = new_location[0] + self.cs_element['offsetTargetX']
-                        source_y = new_location[1] + self.cs_element['offsetTargetY']
+                        target_x = new_location[0] + self.cs_element['offsetTargetX']
+                        target_y = new_location[1] + self.cs_element['offsetTargetY']
+                        print("Move target of line " + self.cs_element['id'])
 
                     self.middle_x = (source_x + target_x) / 2
                     self.middle_y = (source_y + target_y) / 2
 
-                    self.coords(line_element['elem'][0], source_x, source_y, self.middle_x, self.middle_y)
-                    self.coords(line_element['elem'][1], self.middle_x, self.middle_y, target_x, target_y)
+                    self.containing_canvas.coords(self.cs_element['elem'][0], source_x, source_y, self.middle_x, self.middle_y)
+                    self.containing_canvas.coords(self.cs_element['elem'][1], self.middle_x, self.middle_y, target_x, target_y)
                 </script>
-                <raise event="moved_group" scope="narrow" target="parent">
+                <raise event="moved_group" scope="narrow" target="'parent'">
                     <parameter expr="self.cs_element['id']"/>
-                    <parameter expr="self.middle_x, self.middle_y"/>
+                    <parameter expr="(self.middle_x, self.middle_y)"/>
                 </raise>
             </transition>
         </state>

+ 268 - 29
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:   Thu Oct  5 16:46:48 2017
+Date:   Fri Oct  6 08:46:10 2017
 
 Model author: Yentl Van Tendeloo
 Model name:   Modelverse Visual Editor - Tkinter Version 
@@ -7121,33 +7121,6 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
             SCCDWidget.__del__(self)
     
     
-    # user defined method
-    def move_element(self, group_element, new_location):
-        self.group_location[group_element] = new_location
-        if group_element in self.connecting_lines:
-            lines_to_move = self.connecting_lines[group_element]
-        
-            for line_element in lines_to_move:
-                source_x, source_y, _, _ = self.coords(line_element['elem'][0])
-                _, _, target_x, target_y = self.coords(line_element['elem'][1])
-        
-                if line_element['__source'] == group_element:
-                    # Moved source
-                    source_x = self.group_location[group_element][0] + line_element['offsetSourceX']
-                    source_y = self.group_location[group_element][1] + line_element['offsetSourceY']
-                if line_element['__target'] == group_element:
-                    # Moved target
-                    target_x = self.group_location[group_element][0] + line_element['offsetTargetX']
-                    target_y = self.group_location[group_element][1] + line_element['offsetTargetY']
-        
-                middle_x = (source_x + target_x) / 2
-                middle_y = (source_y + target_y) / 2
-        
-                self.coords(line_element['elem'][0], source_x, source_y, middle_x, middle_y)
-                self.coords(line_element['elem'][1], middle_x, middle_y, target_x, target_y)
-                self.move_element(line_element['id'], (middle_x, middle_y))
-    
-    
     # builds Statechart structure
     def build_statechart_structure(self):
         
@@ -7256,7 +7229,7 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         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'])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'connecting_lines', Event("moved_element", None, [group_element, new_location])]))
     
     def _creating_group_0_exec(self, parameters):
         assoc_name = parameters[0]
@@ -7269,6 +7242,266 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         self.default_targets = self.states["/main"].getEffectiveTargetStates()
         RuntimeClassBase.initializeStatechart(self)
 
+class ConnectingLine(RuntimeClassBase, SCCDWidget):
+    def __init__(self, controller, parent, cs_element):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        ConnectingLine.user_defined_constructor(self, parent, cs_element)
+    
+    def user_defined_constructor(self, parent, cs_element):
+        SCCDWidget.__init__(self, True)
+        self.containing_canvas = parent
+        self.cs_element = cs_element
+        self.as_element = cs_element['__asid']
+        self.diff_results = {}
+        self.elements = set()
+    
+    def user_defined_destructor(self):
+        for f in self.elements:
+            self.containing_canvas.delete(f)
+        # call super class destructors
+        if hasattr(SCCDWidget, "__del__"):
+            SCCDWidget.__del__(self)
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, "", self)
+        
+        # state /init
+        self.states["/init"] = State(1, "/init", self)
+        
+        # state /main
+        self.states["/main"] = State(2, "/main", 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)
+        
+        # add children
+        self.states[""].addChild(self.states["/init"])
+        self.states[""].addChild(self.states["/main"])
+        self.states[""].addChild(self.states["/update_attrs"])
+        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[""].fixTree()
+        self.states[""].default_state = self.states["/init"]
+        self.states["/update_attrs"].default_state = self.states["/update_attrs/query"]
+        
+        # transition /init
+        _init_0 = Transition(self, self.states["/init"], [self.states["/main"]])
+        _init_0.setAction(self._init_0_exec)
+        _init_0.setTrigger(None)
+        self.states["/init"].addTransition(_init_0)
+        
+        # transition /main
+        _main_0 = Transition(self, self.states["/main"], [self.states["/update_attrs"]])
+        _main_0.setTrigger(Event("middle-click", None))
+        _main_0.setGuard(self._main_0_guard)
+        self.states["/main"].addTransition(_main_0)
+        _main_1 = Transition(self, self.states["/main"], [self.states["/main"]])
+        _main_1.setAction(self._main_1_exec)
+        _main_1.setTrigger(Event("moved_element", None))
+        _main_1.setGuard(self._main_1_guard)
+        self.states["/main"].addTransition(_main_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))
+        _update_attrs_wait_for_results_1.setGuard(self._update_attrs_wait_for_results_1_guard)
+        self.states["/update_attrs/wait_for_results"].addTransition(_update_attrs_wait_for_results_1)
+        _update_attrs_wait_for_results_2 = Transition(self, self.states["/update_attrs/wait_for_results"], [self.states["/main"]])
+        _update_attrs_wait_for_results_2.setAction(self._update_attrs_wait_for_results_2_exec)
+        _update_attrs_wait_for_results_2.setTrigger(Event("close_window", None))
+        _update_attrs_wait_for_results_2.setGuard(self._update_attrs_wait_for_results_2_guard)
+        self.states["/update_attrs/wait_for_results"].addTransition(_update_attrs_wait_for_results_2)
+        
+        # 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.setAction(self._update_attrs_mark_dirty_0_exec)
+        _update_attrs_mark_dirty_0.setTrigger(Event("mv_response", None))
+        self.states["/update_attrs/mark_dirty"].addTransition(_update_attrs_mark_dirty_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['id'], 'dirty', True]])]))
+    
+    def _init_0_exec(self, parameters):
+        print("Draw connecting line %s from %s to %s" % (self.cs_element['id'], self.cs_element['__source'], self.cs_element['__target']))
+        source_x = self.containing_canvas.group_location[self.cs_element['__source']][0] + self.cs_element['offsetSourceX']
+        source_y = self.containing_canvas.group_location[self.cs_element['__source']][1] + self.cs_element['offsetSourceY']
+        target_x = self.containing_canvas.group_location[self.cs_element['__target']][0] + self.cs_element['offsetTargetX']
+        target_y = self.containing_canvas.group_location[self.cs_element['__target']][1] + self.cs_element['offsetTargetY']
+        middle_x = (source_x + target_x) / 2
+        middle_y = (source_y + target_y) / 2
+        
+        self.containing_canvas.group_location[self.cs_element['id']] = (middle_x, middle_y)
+        
+        line1 = self.containing_canvas.create_line(source_x, source_y, middle_x, middle_y, fill=self.cs_element['lineColour'], width=self.cs_element['lineWidth'], arrow=tk.LAST if self.cs_element['arrow'] else tk.NONE)
+        line2 = self.containing_canvas.create_line(middle_x, middle_y, target_x, target_y, fill=self.cs_element['lineColour'], width=self.cs_element['lineWidth'])
+        self.cs_element['elem'] = (line1, line2)
+        self.elements.add(line1)
+        self.elements.add(line2)
+        
+        self.containing_canvas.lower(line1)
+        self.containing_canvas.lower(line2)
+        
+        self.set_bindable_and_tagorid(self.containing_canvas, line1)
+        self.set_bindable_and_tagorid(self.containing_canvas, line2)
+    
+    def _main_0_guard(self, parameters):
+        ID = parameters[0]
+        return id(self) == ID
+    
+    def _main_1_exec(self, parameters):
+        element = parameters[0]
+        new_location = parameters[1]
+        print("Moving line %s with source %s and target %s" % (self.cs_element['id'], self.cs_element['__source'], self.cs_element['__target']))
+        source_x, source_y, _, _ = self.containing_canvas.coords(self.cs_element['elem'][0])
+        _, _, target_x, target_y = self.containing_canvas.coords(self.cs_element['elem'][1])
+        
+        if element == self.cs_element['__source']:
+            # Changed source of our link
+            source_x = new_location[0] + self.cs_element['offsetSourceX']
+            source_y = new_location[1] + self.cs_element['offsetSourceY']
+            print("Move source of line " + self.cs_element['id'])
+        
+        if element == self.cs_element['__target']:
+            # Changed target of our link
+            target_x = new_location[0] + self.cs_element['offsetTargetX']
+            target_y = new_location[1] + self.cs_element['offsetTargetY']
+            print("Move target of line " + self.cs_element['id'])
+        
+        self.middle_x = (source_x + target_x) / 2
+        self.middle_y = (source_y + target_y) / 2
+        
+        self.containing_canvas.coords(self.cs_element['elem'][0], source_x, source_y, self.middle_x, self.middle_y)
+        self.containing_canvas.coords(self.cs_element['elem'][1], self.middle_x, self.middle_y, target_x, target_y)
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("moved_group", None, [self.cs_element['id'], (self.middle_x, self.middle_y)])]))
+    
+    def _main_1_guard(self, parameters):
+        element = parameters[0]
+        new_location = parameters[1]
+        return element == self.cs_element['__source'] or element == self.cs_element['__target']
+    
+    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]))
+        self.remaining_responses = 0
+    
+    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_wait_for_results_1_guard(self, parameters):
+        return self.remaining_responses > 0
+    
+    def _update_attrs_wait_for_results_2_exec(self, parameters):
+        self.big_step.outputEventOM(Event("delete_instance", None, [self, 'prompt']))
+    
+    def _update_attrs_wait_for_results_2_guard(self, parameters):
+        return self.remaining_responses == 0
+    
+    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 _update_attrs_mark_dirty_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent/parent', Event("rerender_model", None, [])]))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/init"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
 class CanvasElement(RuntimeClassBase, SCCDWidget):
     def __init__(self, controller, parent, coordinates, cs_element, as_element):
         RuntimeClassBase.__init__(self, controller)
@@ -7674,6 +7907,12 @@ class ObjectManager(ObjectManagerBase):
             instance.associations["parent"] = Association("A", 1, 1)
             instance.associations["elements"] = Association("CanvasElement", 0, -1)
             instance.associations["connecting_lines"] = Association("ConnectingLines", 0, -1)
+        elif class_name == "ConnectingLine":
+            instance = ConnectingLine(self.controller, construct_params[0], construct_params[1])
+            instance.associations = {}
+            instance.associations["parent"] = Association("A", 1, 1)
+            instance.associations["elements"] = Association("CanvasElement", 0, -1)
+            instance.associations["prompt"] = Association("PromptWindow", 0, -1)
         elif class_name == "CanvasElement":
             instance = CanvasElement(self.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3])
             instance.associations = {}