浏览代码

Various bugfixes in GUI

Yentl Van Tendeloo 7 年之前
父节点
当前提交
373027b213
共有 3 个文件被更改,包括 296 次插入93 次删除
  1. 17 11
      classes/canvas/canvas.xml
  2. 114 37
      classes/canvas/connecting_line.xml
  3. 165 45
      frontend.py

+ 17 - 11
classes/canvas/canvas.xml

@@ -145,8 +145,10 @@
                     <transition event="deleted_group" target=".">
                     <transition event="deleted_group" target=".">
                         <parameter name="group_element"/>
                         <parameter name="group_element"/>
                         <script>
                         <script>
-                            del self.group_location[group_element]
-                            print("Remove group_location " + str(group_element))
+                            try:
+                                del self.group_location[group_element]
+                            except KeyError:
+                                pass
                         </script>
                         </script>
                         <raise event="deleted_element" scope="narrow" target="'connecting_lines'">
                         <raise event="deleted_element" scope="narrow" target="'connecting_lines'">
                             <parameter expr="group_element"/>
                             <parameter expr="group_element"/>
@@ -162,6 +164,13 @@
                         </script>
                         </script>
                     </onentry>
                     </onentry>
 
 
+                    <onexit>
+                        <script>
+                            self.delete(self.tmp_line)
+                            self.tmp_line = None
+                        </script>
+                    </onexit>
+
                     <state id="drawing">
                     <state id="drawing">
                         <transition event="motion" target=".">
                         <transition event="motion" target=".">
                             <script>
                             <script>
@@ -184,10 +193,6 @@
 
 
                         <transition event="right-click" cond="ID == id(self) and not control_pressed" target="../../ready">
                         <transition event="right-click" cond="ID == id(self) and not control_pressed" target="../../ready">
                             <parameter name="ID"/>
                             <parameter name="ID"/>
-                            <script>
-                                self.delete(self.tmp_line)
-                                self.tmp_line = None
-                            </script>
                         </transition>
                         </transition>
 
 
                         <transition event="create_line" target="../create_in_mv">
                         <transition event="create_line" target="../create_in_mv">
@@ -227,7 +232,12 @@
                         </state>
                         </state>
 
 
                         <state id="check_types">
                         <state id="check_types">
-                            <transition cond="len(self.allowed_types) == 0" target="../../../ready"/>
+                            <transition cond="len(self.allowed_types) == 0" target="../../../ready">
+                                <raise event="errorlog_log" scope="broad">
+                                    <parameter expr="'No allowed associations from %s to %s' % (self.creating_line[1], self.creating_line[3])"/>
+                                </raise>
+                            </transition>
+
                             <transition cond="len(self.allowed_types) == 1" target="../create">
                             <transition cond="len(self.allowed_types) == 1" target="../create">
                                 <script>
                                 <script>
                                     self.assoc_type = self.allowed_types.pop()
                                     self.assoc_type = self.allowed_types.pop()
@@ -322,10 +332,6 @@
                                     <raise event="delete_instance" scope="cd">
                                     <raise event="delete_instance" scope="cd">
                                         <parameter expr="'prompt'"/>
                                         <parameter expr="'prompt'"/>
                                     </raise>
                                     </raise>
-                                    <script>
-                                        self.delete(self.tmp_line)
-                                        self.tmp_line = None
-                                    </script>
                                 </transition>
                                 </transition>
                             </state>
                             </state>
                         </state>
                         </state>

+ 114 - 37
classes/canvas/connecting_line.xml

@@ -94,6 +94,7 @@
                 <parameter name="ID"/>
                 <parameter name="ID"/>
                 <raise event="modify_defined_attrs" scope="narrow" target="'parent/parent'">
                 <raise event="modify_defined_attrs" scope="narrow" target="'parent/parent'">
                     <parameter expr="self.as_element"/>
                     <parameter expr="self.as_element"/>
+                    <parameter expr="self.cs_element"/>
                 </raise>
                 </raise>
             </transition>
             </transition>
 
 
@@ -179,21 +180,65 @@
                     </raise>
                     </raise>
                 </onentry>
                 </onentry>
 
 
-                <transition event="mv_response" target="../prompt">
-                    <parameter name="result"/>
-                    <script>
-                        self.prev_results = {k: json.dumps(v) for k, v in result.items()}
-                    </script>
-                </transition>
-
                 <transition event="mv_exception" target="../../main">
                 <transition event="mv_exception" target="../../main">
                     <parameter name="ID"/>
                     <parameter name="ID"/>
                     <parameter name="exception_name"/>
                     <parameter name="exception_name"/>
                     <parameter name="description"/>
                     <parameter name="description"/>
                     <raise event="errorlog_log" scope="broad">
                     <raise event="errorlog_log" scope="broad">
-                        <parameter expr="'Could not read attributes: %s -- %s' % (exception_name, description)"/>
+                        <parameter expr="'Failed to read attributes: %s -- %s' % (exception_name, description)"/>
                     </raise>
                     </raise>
                 </transition>
                 </transition>
+
+                <transition event="mv_response" target="../translate_AL">
+                    <parameter name="result"/>
+                    <script>
+                        self.prev_results = {}
+                        for k, v in result.items():
+                            if not isinstance(v, dict):
+                                if v is not None:
+                                    try:
+                                        self.prev_results[k] = json.dumps(v)
+                                    except:
+                                        self.prev_results[k] = "!! ERROR -- cannot decode attribute !!"
+                                else:
+                                    self.prev_results[k] = ""
+                        self.al = {k: v for k, v in result.items() if isinstance(v, dict)}
+                        self.al_keys = self.al.keys()
+                    </script>
+                </transition>
+            </state>
+
+            <state id="translate_AL" initial="check">
+                <state id="check">
+                    <transition cond="not self.al" target="../../prompt"/>
+                    <transition cond="self.al" target="../process">
+                        <script>
+                            self.attr_name, self.attr_dict = self.al.popitem()
+                        </script>
+                        <raise event="mv_request" scope="broad">
+                            <parameter expr="'AL_text'"/>
+                            <parameter expr="[self.attr_dict['AL']]"/>
+                        </raise>
+                    </transition>
+                </state>
+
+                <state id="process">
+                    <transition event="mv_exception" target="../../../main">
+                        <parameter name="ID"/>
+                        <parameter name="exception_name"/>
+                        <parameter name="description"/>
+                        <raise event="errorlog_log" scope="broad">
+                            <parameter expr="'Failed to read Action Language fragment: %s -- %s' % (exception_name, description)"/>
+                        </raise>
+                    </transition>
+
+                    <transition event="mv_response" target="../check">
+                        <parameter name="result"/>
+                        <script>
+                            self.prev_results[self.attr_name] = result.rstrip() + "\n"
+                        </script>
+                    </transition>
+                </state>
             </state>
             </state>
 
 
             <state id="prompt">
             <state id="prompt">
@@ -223,7 +268,11 @@
                     <script>
                     <script>
                         for k in results:
                         for k in results:
                             if results[k] != self.prev_results[k]:
                             if results[k] != self.prev_results[k]:
-                                self.diff_results[k] = results[k]
+                                if k in self.al_keys:
+                                    if results[k].strip() != self.prev_results[k].strip():
+                                        self.diff_results[k] = results[k]
+                                else:
+                                    self.diff_results[k] = results[k]
                         self.remaining_responses = len(self.diff_results)
                         self.remaining_responses = len(self.diff_results)
                     </script>
                     </script>
                 </transition>
                 </transition>
@@ -242,57 +291,85 @@
             </state>
             </state>
 
 
             <state id="process_results">
             <state id="process_results">
+                <onentry>
+                    <script>
+                    </script>
+                </onentry>
+
                 <transition cond="len(self.diff_results) > 0" target=".">
                 <transition cond="len(self.diff_results) > 0" target=".">
                     <script>
                     <script>
                         k, v = self.diff_results.popitem()
                         k, v = self.diff_results.popitem()
+                        v = v.strip()
+                        if v == "":
+                            op = "attr_delete"
+                            params = [current_model, self.as_element, k]
+                        else:
+                            if k in self.al_keys:
+                                op = "attr_assign_code"
+                                params = [current_model, self.as_element, k, v]
+                            else:
+                                op = "attr_assign"
+                                try:
+                                    v = json.loads(v)
+                                except:
+                                    v = str(v)
+                                params = [current_model, self.as_element, k, v]
                     </script>
                     </script>
                     <raise event="mv_request" scope="broad">
                     <raise event="mv_request" scope="broad">
-                        <parameter expr="'attr_assign'"/>
-                        <parameter expr="[current_model, self.as_element, k, json.loads(v)]"/>
+                        <parameter expr="op"/>
+                        <parameter expr="params"/>
                     </raise>
                     </raise>
                 </transition>
                 </transition>
 
 
                 <transition cond="self.remaining_responses == 0" target="../mark_dirty"/>
                 <transition cond="self.remaining_responses == 0" target="../mark_dirty"/>
 
 
-                <transition event="mv_response" target=".">
-                    <script>
-                        self.remaining_responses -= 1
-                    </script>
-                </transition>
-
                 <transition event="mv_exception" target=".">
                 <transition event="mv_exception" target=".">
                     <parameter name="ID"/>
                     <parameter name="ID"/>
                     <parameter name="exception_name"/>
                     <parameter name="exception_name"/>
                     <parameter name="description"/>
                     <parameter name="description"/>
                     <raise event="errorlog_log" scope="broad">
                     <raise event="errorlog_log" scope="broad">
-                        <parameter expr="'Could not assign attributes: %s -- %s' % (exception_name, description)"/>
+                        <parameter expr="'Failed to set attribute: %s - %s' % (exception_name, description)"/>
                     </raise>
                     </raise>
                     <script>
                     <script>
                         self.remaining_responses -= 1
                         self.remaining_responses -= 1
                     </script>
                     </script>
                 </transition>
                 </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['id'], 'dirty', True]"/>
-                    </raise>
-                </onentry>
 
 
-                <transition event="mv_response" target="../../main">
-                    <raise event="minimal_rerender_model" scope="narrow" target="'parent/parent'"/>
+                <transition event="mv_response" target=".">
+                    <script>
+                        self.remaining_responses -= 1
+                    </script>
                 </transition>
                 </transition>
+            </state>
 
 
-                <transition event="mv_exception" target="../../main">
-                    <parameter name="ID"/>
-                    <parameter name="exception_name"/>
-                    <parameter name="description"/>
-                    <raise event="errorlog_log" scope="broad">
-                        <parameter expr="'Could not mark element as dirty: %s -- %s' % (exception_name, description)"/>
-                    </raise>
-                </transition>
+            <state id="mark_dirty" initial="check">
+                <state id="check">
+                    <transition cond="current_rendered_model" target="../do"/>
+                    <transition cond="not current_rendered_model" target="../../../main">
+                        <raise event="minimal_rerender_model" scope="narrow" target="'parent/parent'"/>
+                    </transition>
+                </state>
+
+                <state id="do">
+                    <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="../../../main">
+                        <raise event="minimal_rerender_model" scope="narrow" target="'parent/parent'"/>
+                    </transition>
+                    <transition event="mv_exception" target="../../../main">
+                        <parameter name="ID"/>
+                        <parameter name="exception_name"/>
+                        <parameter name="description"/>
+                        <raise event="errorlog_log" scope="broad">
+                            <parameter expr="'Could not assign attribute: %s -- %s' % (exception_name, description)"/>
+                        </raise>
+                    </transition>
+
+                </state>
             </state>
             </state>
         </state>
         </state>
     </scxml>
     </scxml>

+ 165 - 45
frontend.py

@@ -14021,6 +14021,7 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         # state /ready/process_events/creating_line
         # 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"] = 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"].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
         # state /ready/process_events/creating_line/drawing
         self.states["/ready/process_events/creating_line/drawing"] = State(6, "/ready/process_events/creating_line/drawing", self)
         self.states["/ready/process_events/creating_line/drawing"] = State(6, "/ready/process_events/creating_line/drawing", self)
@@ -14165,7 +14166,6 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         _ready_process_events_creating_line_drawing_0.setTrigger(Event("motion", None))
         _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)
         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 = 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.setTrigger(Event("right-click", None))
         _ready_process_events_creating_line_drawing_1.setGuard(self._ready_process_events_creating_line_drawing_1_guard)
         _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)
         self.states["/ready/process_events/creating_line/drawing"].addTransition(_ready_process_events_creating_line_drawing_1)
@@ -14186,6 +14186,7 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         
         
         # transition /ready/process_events/creating_line/create_in_mv/check_types
         # transition /ready/process_events/creating_line/create_in_mv/check_types
         _ready_process_events_creating_line_create_in_mv_check_types_0 = Transition(self, self.states["/ready/process_events/creating_line/create_in_mv/check_types"], [self.states["/ready/process_events/ready"]])
         _ready_process_events_creating_line_create_in_mv_check_types_0 = Transition(self, self.states["/ready/process_events/creating_line/create_in_mv/check_types"], [self.states["/ready/process_events/ready"]])
+        _ready_process_events_creating_line_create_in_mv_check_types_0.setAction(self._ready_process_events_creating_line_create_in_mv_check_types_0_exec)
         _ready_process_events_creating_line_create_in_mv_check_types_0.setTrigger(None)
         _ready_process_events_creating_line_create_in_mv_check_types_0.setTrigger(None)
         _ready_process_events_creating_line_create_in_mv_check_types_0.setGuard(self._ready_process_events_creating_line_create_in_mv_check_types_0_guard)
         _ready_process_events_creating_line_create_in_mv_check_types_0.setGuard(self._ready_process_events_creating_line_create_in_mv_check_types_0_guard)
         self.states["/ready/process_events/creating_line/create_in_mv/check_types"].addTransition(_ready_process_events_creating_line_create_in_mv_check_types_0)
         self.states["/ready/process_events/creating_line/create_in_mv/check_types"].addTransition(_ready_process_events_creating_line_create_in_mv_check_types_0)
@@ -14294,6 +14295,10 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
     def _ready_process_events_creating_line_enter(self):
     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)
         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)
+        self.tmp_line = None
+    
     def _ready_process_events_creating_line_create_in_mv_request_user_enter(self):
     def _ready_process_events_creating_line_create_in_mv_request_user_enter(self):
         self.new_allowed_types = {}
         self.new_allowed_types = {}
     
     
@@ -14390,8 +14395,10 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
     
     
     def _ready_process_events_ready_9_exec(self, parameters):
     def _ready_process_events_ready_9_exec(self, parameters):
         group_element = parameters[0]
         group_element = parameters[0]
-        del self.group_location[group_element]
-        print("Remove group_location " + str(group_element))
+        try:
+            del self.group_location[group_element]
+        except KeyError:
+            pass
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'connecting_lines', Event("deleted_element", None, [group_element])]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'connecting_lines', Event("deleted_element", None, [group_element])]))
     
     
     def _ready_process_events_creating_line_drawing_0_exec(self, parameters):
     def _ready_process_events_creating_line_drawing_0_exec(self, parameters):
@@ -14410,11 +14417,6 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         
         
         self.coords(self.tmp_line, x, y, self.last_x, self.last_y)
         self.coords(self.tmp_line, x, y, self.last_x, self.last_y)
     
     
-    def _ready_process_events_creating_line_drawing_1_exec(self, parameters):
-        ID = parameters[0]
-        self.delete(self.tmp_line)
-        self.tmp_line = None
-    
     def _ready_process_events_creating_line_drawing_1_guard(self, parameters):
     def _ready_process_events_creating_line_drawing_1_guard(self, parameters):
         ID = parameters[0]
         ID = parameters[0]
         return ID == id(self) and not control_pressed
         return ID == id(self) and not control_pressed
@@ -14435,6 +14437,9 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
         description = parameters[2]
         description = parameters[2]
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not query connections between elements: %s -- %s' % (exception_name, description)])]))
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not query connections between elements: %s -- %s' % (exception_name, description)])]))
     
     
+    def _ready_process_events_creating_line_create_in_mv_check_types_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['No allowed associations from %s to %s' % (self.creating_line[1], self.creating_line[3])])]))
+    
     def _ready_process_events_creating_line_create_in_mv_check_types_0_guard(self, parameters):
     def _ready_process_events_creating_line_create_in_mv_check_types_0_guard(self, parameters):
         return len(self.allowed_types) == 0
         return len(self.allowed_types) == 0
     
     
@@ -14488,8 +14493,6 @@ class Canvas(RuntimeClassBase, tk.Canvas, SCCDWidget):
     
     
     def _ready_process_events_creating_line_create_in_mv_request_user_wait_for_response_2_exec(self, parameters):
     def _ready_process_events_creating_line_create_in_mv_request_user_wait_for_response_2_exec(self, parameters):
         self.big_step.outputEventOM(Event("delete_instance", None, [self, 'prompt']))
         self.big_step.outputEventOM(Event("delete_instance", None, [self, 'prompt']))
-        self.delete(self.tmp_line)
-        self.tmp_line = None
     
     
     def _ready_process_events_creating_line_create_in_mv_request_user_wait_for_response_2_guard(self, parameters):
     def _ready_process_events_creating_line_create_in_mv_request_user_wait_for_response_2_guard(self, parameters):
         return self.assoc_type is None
         return self.assoc_type is None
@@ -14608,19 +14611,35 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         self.states["/update_attrs/query"] = State(6, "/update_attrs/query", self)
         self.states["/update_attrs/query"] = State(6, "/update_attrs/query", self)
         self.states["/update_attrs/query"].setEnter(self._update_attrs_query_enter)
         self.states["/update_attrs/query"].setEnter(self._update_attrs_query_enter)
         
         
+        # state /update_attrs/translate_AL
+        self.states["/update_attrs/translate_AL"] = State(7, "/update_attrs/translate_AL", self)
+        
+        # state /update_attrs/translate_AL/check
+        self.states["/update_attrs/translate_AL/check"] = State(8, "/update_attrs/translate_AL/check", self)
+        
+        # state /update_attrs/translate_AL/process
+        self.states["/update_attrs/translate_AL/process"] = State(9, "/update_attrs/translate_AL/process", self)
+        
         # state /update_attrs/prompt
         # state /update_attrs/prompt
-        self.states["/update_attrs/prompt"] = State(7, "/update_attrs/prompt", self)
+        self.states["/update_attrs/prompt"] = State(10, "/update_attrs/prompt", self)
         self.states["/update_attrs/prompt"].setEnter(self._update_attrs_prompt_enter)
         self.states["/update_attrs/prompt"].setEnter(self._update_attrs_prompt_enter)
         
         
         # state /update_attrs/wait_for_results
         # state /update_attrs/wait_for_results
-        self.states["/update_attrs/wait_for_results"] = State(8, "/update_attrs/wait_for_results", self)
+        self.states["/update_attrs/wait_for_results"] = State(11, "/update_attrs/wait_for_results", self)
         
         
         # state /update_attrs/process_results
         # state /update_attrs/process_results
-        self.states["/update_attrs/process_results"] = State(9, "/update_attrs/process_results", self)
+        self.states["/update_attrs/process_results"] = State(12, "/update_attrs/process_results", self)
+        self.states["/update_attrs/process_results"].setEnter(self._update_attrs_process_results_enter)
         
         
         # state /update_attrs/mark_dirty
         # state /update_attrs/mark_dirty
-        self.states["/update_attrs/mark_dirty"] = State(10, "/update_attrs/mark_dirty", self)
-        self.states["/update_attrs/mark_dirty"].setEnter(self._update_attrs_mark_dirty_enter)
+        self.states["/update_attrs/mark_dirty"] = State(13, "/update_attrs/mark_dirty", self)
+        
+        # state /update_attrs/mark_dirty/check
+        self.states["/update_attrs/mark_dirty/check"] = State(14, "/update_attrs/mark_dirty/check", self)
+        
+        # state /update_attrs/mark_dirty/do
+        self.states["/update_attrs/mark_dirty/do"] = State(15, "/update_attrs/mark_dirty/do", self)
+        self.states["/update_attrs/mark_dirty/do"].setEnter(self._update_attrs_mark_dirty_do_enter)
         
         
         # add children
         # add children
         self.states[""].addChild(self.states["/init"])
         self.states[""].addChild(self.states["/init"])
@@ -14629,13 +14648,20 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         self.states[""].addChild(self.states["/remove_element"])
         self.states[""].addChild(self.states["/remove_element"])
         self.states[""].addChild(self.states["/update_attrs"])
         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/query"])
+        self.states["/update_attrs"].addChild(self.states["/update_attrs/translate_AL"])
         self.states["/update_attrs"].addChild(self.states["/update_attrs/prompt"])
         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/wait_for_results"])
         self.states["/update_attrs"].addChild(self.states["/update_attrs/process_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_attrs"].addChild(self.states["/update_attrs/mark_dirty"])
+        self.states["/update_attrs/translate_AL"].addChild(self.states["/update_attrs/translate_AL/check"])
+        self.states["/update_attrs/translate_AL"].addChild(self.states["/update_attrs/translate_AL/process"])
+        self.states["/update_attrs/mark_dirty"].addChild(self.states["/update_attrs/mark_dirty/check"])
+        self.states["/update_attrs/mark_dirty"].addChild(self.states["/update_attrs/mark_dirty/do"])
         self.states[""].fixTree()
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/init"]
         self.states[""].default_state = self.states["/init"]
         self.states["/update_attrs"].default_state = self.states["/update_attrs/query"]
         self.states["/update_attrs"].default_state = self.states["/update_attrs/query"]
+        self.states["/update_attrs/translate_AL"].default_state = self.states["/update_attrs/translate_AL/check"]
+        self.states["/update_attrs/mark_dirty"].default_state = self.states["/update_attrs/mark_dirty/check"]
         
         
         # transition /init
         # transition /init
         _init_0 = Transition(self, self.states["/init"], [self.states["/main"]])
         _init_0 = Transition(self, self.states["/init"], [self.states["/main"]])
@@ -14684,15 +14710,36 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         self.states["/remove_element"].addTransition(_remove_element_1)
         self.states["/remove_element"].addTransition(_remove_element_1)
         
         
         # transition /update_attrs/query
         # transition /update_attrs/query
-        _update_attrs_query_0 = Transition(self, self.states["/update_attrs/query"], [self.states["/update_attrs/prompt"]])
+        _update_attrs_query_0 = Transition(self, self.states["/update_attrs/query"], [self.states["/main"]])
         _update_attrs_query_0.setAction(self._update_attrs_query_0_exec)
         _update_attrs_query_0.setAction(self._update_attrs_query_0_exec)
-        _update_attrs_query_0.setTrigger(Event("mv_response", None))
+        _update_attrs_query_0.setTrigger(Event("mv_exception", None))
         self.states["/update_attrs/query"].addTransition(_update_attrs_query_0)
         self.states["/update_attrs/query"].addTransition(_update_attrs_query_0)
-        _update_attrs_query_1 = Transition(self, self.states["/update_attrs/query"], [self.states["/main"]])
+        _update_attrs_query_1 = Transition(self, self.states["/update_attrs/query"], [self.states["/update_attrs/translate_AL"]])
         _update_attrs_query_1.setAction(self._update_attrs_query_1_exec)
         _update_attrs_query_1.setAction(self._update_attrs_query_1_exec)
-        _update_attrs_query_1.setTrigger(Event("mv_exception", None))
+        _update_attrs_query_1.setTrigger(Event("mv_response", None))
         self.states["/update_attrs/query"].addTransition(_update_attrs_query_1)
         self.states["/update_attrs/query"].addTransition(_update_attrs_query_1)
         
         
+        # transition /update_attrs/translate_AL/check
+        _update_attrs_translate_AL_check_0 = Transition(self, self.states["/update_attrs/translate_AL/check"], [self.states["/update_attrs/prompt"]])
+        _update_attrs_translate_AL_check_0.setTrigger(None)
+        _update_attrs_translate_AL_check_0.setGuard(self._update_attrs_translate_AL_check_0_guard)
+        self.states["/update_attrs/translate_AL/check"].addTransition(_update_attrs_translate_AL_check_0)
+        _update_attrs_translate_AL_check_1 = Transition(self, self.states["/update_attrs/translate_AL/check"], [self.states["/update_attrs/translate_AL/process"]])
+        _update_attrs_translate_AL_check_1.setAction(self._update_attrs_translate_AL_check_1_exec)
+        _update_attrs_translate_AL_check_1.setTrigger(None)
+        _update_attrs_translate_AL_check_1.setGuard(self._update_attrs_translate_AL_check_1_guard)
+        self.states["/update_attrs/translate_AL/check"].addTransition(_update_attrs_translate_AL_check_1)
+        
+        # transition /update_attrs/translate_AL/process
+        _update_attrs_translate_AL_process_0 = Transition(self, self.states["/update_attrs/translate_AL/process"], [self.states["/main"]])
+        _update_attrs_translate_AL_process_0.setAction(self._update_attrs_translate_AL_process_0_exec)
+        _update_attrs_translate_AL_process_0.setTrigger(Event("mv_exception", None))
+        self.states["/update_attrs/translate_AL/process"].addTransition(_update_attrs_translate_AL_process_0)
+        _update_attrs_translate_AL_process_1 = Transition(self, self.states["/update_attrs/translate_AL/process"], [self.states["/update_attrs/translate_AL/check"]])
+        _update_attrs_translate_AL_process_1.setAction(self._update_attrs_translate_AL_process_1_exec)
+        _update_attrs_translate_AL_process_1.setTrigger(Event("mv_response", None))
+        self.states["/update_attrs/translate_AL/process"].addTransition(_update_attrs_translate_AL_process_1)
+        
         # transition /update_attrs/prompt
         # 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 = 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.setAction(self._update_attrs_prompt_0_exec)
@@ -14727,22 +14774,33 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_1)
         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 = 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.setAction(self._update_attrs_process_results_2_exec)
-        _update_attrs_process_results_2.setTrigger(Event("mv_response", None))
+        _update_attrs_process_results_2.setTrigger(Event("mv_exception", None))
         self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_2)
         self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_2)
         _update_attrs_process_results_3 = Transition(self, self.states["/update_attrs/process_results"], [self.states["/update_attrs/process_results"]])
         _update_attrs_process_results_3 = Transition(self, self.states["/update_attrs/process_results"], [self.states["/update_attrs/process_results"]])
         _update_attrs_process_results_3.setAction(self._update_attrs_process_results_3_exec)
         _update_attrs_process_results_3.setAction(self._update_attrs_process_results_3_exec)
-        _update_attrs_process_results_3.setTrigger(Event("mv_exception", None))
+        _update_attrs_process_results_3.setTrigger(Event("mv_response", None))
         self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_3)
         self.states["/update_attrs/process_results"].addTransition(_update_attrs_process_results_3)
         
         
-        # 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)
-        _update_attrs_mark_dirty_1 = Transition(self, self.states["/update_attrs/mark_dirty"], [self.states["/main"]])
-        _update_attrs_mark_dirty_1.setAction(self._update_attrs_mark_dirty_1_exec)
-        _update_attrs_mark_dirty_1.setTrigger(Event("mv_exception", None))
-        self.states["/update_attrs/mark_dirty"].addTransition(_update_attrs_mark_dirty_1)
+        # transition /update_attrs/mark_dirty/check
+        _update_attrs_mark_dirty_check_0 = Transition(self, self.states["/update_attrs/mark_dirty/check"], [self.states["/update_attrs/mark_dirty/do"]])
+        _update_attrs_mark_dirty_check_0.setTrigger(None)
+        _update_attrs_mark_dirty_check_0.setGuard(self._update_attrs_mark_dirty_check_0_guard)
+        self.states["/update_attrs/mark_dirty/check"].addTransition(_update_attrs_mark_dirty_check_0)
+        _update_attrs_mark_dirty_check_1 = Transition(self, self.states["/update_attrs/mark_dirty/check"], [self.states["/main"]])
+        _update_attrs_mark_dirty_check_1.setAction(self._update_attrs_mark_dirty_check_1_exec)
+        _update_attrs_mark_dirty_check_1.setTrigger(None)
+        _update_attrs_mark_dirty_check_1.setGuard(self._update_attrs_mark_dirty_check_1_guard)
+        self.states["/update_attrs/mark_dirty/check"].addTransition(_update_attrs_mark_dirty_check_1)
+        
+        # transition /update_attrs/mark_dirty/do
+        _update_attrs_mark_dirty_do_0 = Transition(self, self.states["/update_attrs/mark_dirty/do"], [self.states["/main"]])
+        _update_attrs_mark_dirty_do_0.setAction(self._update_attrs_mark_dirty_do_0_exec)
+        _update_attrs_mark_dirty_do_0.setTrigger(Event("mv_response", None))
+        self.states["/update_attrs/mark_dirty/do"].addTransition(_update_attrs_mark_dirty_do_0)
+        _update_attrs_mark_dirty_do_1 = Transition(self, self.states["/update_attrs/mark_dirty/do"], [self.states["/main"]])
+        _update_attrs_mark_dirty_do_1.setAction(self._update_attrs_mark_dirty_do_1_exec)
+        _update_attrs_mark_dirty_do_1.setTrigger(Event("mv_exception", None))
+        self.states["/update_attrs/mark_dirty/do"].addTransition(_update_attrs_mark_dirty_do_1)
     
     
     def _remove_element_enter(self):
     def _remove_element_enter(self):
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['delete_element', [current_model, self.as_element]])]))
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['delete_element', [current_model, self.as_element]])]))
@@ -14757,8 +14815,11 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
     def _update_attrs_prompt_enter(self):
     def _update_attrs_prompt_enter(self):
         self.big_step.outputEventOM(Event("create_instance", None, [self, 'prompt', 'PromptWindow', self.prev_results, {}]))
         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 _update_attrs_process_results_enter(self):
+        pass
+    
+    def _update_attrs_mark_dirty_do_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 _init_0_exec(self, parameters):
     def _init_0_exec(self, parameters):
         source_x = self.containing_canvas.group_location[self.cs_element['__source']][0] + self.cs_element['offsetSourceX']
         source_x = self.containing_canvas.group_location[self.cs_element['__source']][0] + self.cs_element['offsetSourceX']
@@ -14807,7 +14868,7 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
     
     
     def _main_3_exec(self, parameters):
     def _main_3_exec(self, parameters):
         ID = parameters[0]
         ID = parameters[0]
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent/parent', Event("modify_defined_attrs", None, [self.as_element])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent/parent', Event("modify_defined_attrs", None, [self.as_element, self.cs_element])]))
     
     
     def _main_3_guard(self, parameters):
     def _main_3_guard(self, parameters):
         ID = parameters[0]
         ID = parameters[0]
@@ -14859,14 +14920,45 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not delete element: %s -- %s' % (exception_name, description)])]))
         self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not delete element: %s -- %s' % (exception_name, description)])]))
     
     
     def _update_attrs_query_0_exec(self, parameters):
     def _update_attrs_query_0_exec(self, parameters):
-        result = parameters[0]
-        self.prev_results = {k: json.dumps(v) for k, v in result.items()}
+        ID = parameters[0]
+        exception_name = parameters[1]
+        description = parameters[2]
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Failed to read attributes: %s -- %s' % (exception_name, description)])]))
     
     
     def _update_attrs_query_1_exec(self, parameters):
     def _update_attrs_query_1_exec(self, parameters):
+        result = parameters[0]
+        self.prev_results = {}
+        for k, v in result.items():
+            if not isinstance(v, dict):
+                if v is not None:
+                    try:
+                        self.prev_results[k] = json.dumps(v)
+                    except:
+                        self.prev_results[k] = "!! ERROR -- cannot decode attribute !!"
+                else:
+                    self.prev_results[k] = ""
+        self.al = {k: v for k, v in result.items() if isinstance(v, dict)}
+        self.al_keys = self.al.keys()
+    
+    def _update_attrs_translate_AL_check_0_guard(self, parameters):
+        return not self.al
+    
+    def _update_attrs_translate_AL_check_1_exec(self, parameters):
+        self.attr_name, self.attr_dict = self.al.popitem()
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, ['AL_text', [self.attr_dict['AL']]])]))
+    
+    def _update_attrs_translate_AL_check_1_guard(self, parameters):
+        return self.al
+    
+    def _update_attrs_translate_AL_process_0_exec(self, parameters):
         ID = parameters[0]
         ID = parameters[0]
         exception_name = parameters[1]
         exception_name = parameters[1]
         description = parameters[2]
         description = parameters[2]
-        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not read attributes: %s -- %s' % (exception_name, description)])]))
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Failed to read Action Language fragment: %s -- %s' % (exception_name, description)])]))
+    
+    def _update_attrs_translate_AL_process_1_exec(self, parameters):
+        result = parameters[0]
+        self.prev_results[self.attr_name] = result.rstrip() + "\n"
     
     
     def _update_attrs_prompt_0_exec(self, parameters):
     def _update_attrs_prompt_0_exec(self, parameters):
         name = parameters[0]
         name = parameters[0]
@@ -14877,7 +14969,11 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         results = parameters[0]
         results = parameters[0]
         for k in results:
         for k in results:
             if results[k] != self.prev_results[k]:
             if results[k] != self.prev_results[k]:
-                self.diff_results[k] = results[k]
+                if k in self.al_keys:
+                    if results[k].strip() != self.prev_results[k].strip():
+                        self.diff_results[k] = results[k]
+                else:
+                    self.diff_results[k] = results[k]
         self.remaining_responses = len(self.diff_results)
         self.remaining_responses = len(self.diff_results)
     
     
     def _update_attrs_wait_for_results_1_exec(self, parameters):
     def _update_attrs_wait_for_results_1_exec(self, parameters):
@@ -14894,7 +14990,22 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
     
     
     def _update_attrs_process_results_0_exec(self, parameters):
     def _update_attrs_process_results_0_exec(self, parameters):
         k, v = self.diff_results.popitem()
         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, json.loads(v)]])]))
+        v = v.strip()
+        if v == "":
+            op = "attr_delete"
+            params = [current_model, self.as_element, k]
+        else:
+            if k in self.al_keys:
+                op = "attr_assign_code"
+                params = [current_model, self.as_element, k, v]
+            else:
+                op = "attr_assign"
+                try:
+                    v = json.loads(v)
+                except:
+                    v = str(v)
+                params = [current_model, self.as_element, k, v]
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("mv_request", None, [op, params])]))
     
     
     def _update_attrs_process_results_0_guard(self, parameters):
     def _update_attrs_process_results_0_guard(self, parameters):
         return len(self.diff_results) > 0
         return len(self.diff_results) > 0
@@ -14903,23 +15014,32 @@ class ConnectingLine(RuntimeClassBase, SCCDWidget):
         return self.remaining_responses == 0
         return self.remaining_responses == 0
     
     
     def _update_attrs_process_results_2_exec(self, parameters):
     def _update_attrs_process_results_2_exec(self, parameters):
-        self.remaining_responses -= 1
-    
-    def _update_attrs_process_results_3_exec(self, parameters):
         ID = parameters[0]
         ID = parameters[0]
         exception_name = parameters[1]
         exception_name = parameters[1]
         description = parameters[2]
         description = parameters[2]
-        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not assign attributes: %s -- %s' % (exception_name, description)])]))
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Failed to set attribute: %s - %s' % (exception_name, description)])]))
+        self.remaining_responses -= 1
+    
+    def _update_attrs_process_results_3_exec(self, parameters):
         self.remaining_responses -= 1
         self.remaining_responses -= 1
     
     
-    def _update_attrs_mark_dirty_0_exec(self, parameters):
+    def _update_attrs_mark_dirty_check_0_guard(self, parameters):
+        return current_rendered_model
+    
+    def _update_attrs_mark_dirty_check_1_exec(self, parameters):
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent/parent', Event("minimal_rerender_model", None, [])]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent/parent', Event("minimal_rerender_model", None, [])]))
     
     
-    def _update_attrs_mark_dirty_1_exec(self, parameters):
+    def _update_attrs_mark_dirty_check_1_guard(self, parameters):
+        return not current_rendered_model
+    
+    def _update_attrs_mark_dirty_do_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent/parent', Event("minimal_rerender_model", None, [])]))
+    
+    def _update_attrs_mark_dirty_do_1_exec(self, parameters):
         ID = parameters[0]
         ID = parameters[0]
         exception_name = parameters[1]
         exception_name = parameters[1]
         description = parameters[2]
         description = parameters[2]
-        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not mark element as dirty: %s -- %s' % (exception_name, description)])]))
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("errorlog_log", None, ['Could not assign attribute: %s -- %s' % (exception_name, description)])]))
     
     
     def initializeStatechart(self):
     def initializeStatechart(self):
         # enter default state
         # enter default state