Viewer.py
changeset 383 25ffba02b6a8
parent 381 98890d848701
child 384 ed27a676d5c9
--- a/Viewer.py	Fri Jul 24 09:55:11 2009 +0200
+++ b/Viewer.py	Fri Jul 24 10:47:35 2009 +0200
@@ -76,6 +76,102 @@
 
 ZOOM_FACTORS = [math.sqrt(2) ** x for x in xrange(-6, 7)]
 
+
+def GetVariableCreationFunction(variable_type):
+    def variableCreationFunction(viewer, id, specific_values):
+        return FBD_Variable(viewer, variable_type, 
+                                    specific_values["name"], 
+                                    specific_values["value_type"], 
+                                    id,
+                                    specific_values["executionOrder"])
+    return variableCreationFunction
+
+def GetConnectorCreationFunction(connector_type):
+    def connectorCreationFunction(viewer, id, specific_values):
+        return FBD_Connector(viewer, connector_type, 
+                                     specific_values["name"], id)
+    return connectorCreationFunction
+
+def commentCreationFunction(viewer, id, specific_values):
+    return Comment(viewer, specific_values["content"], id)
+
+def GetPowerRailCreationFunction(powerrail_type):
+    def powerRailCreationFunction(viewer, id, specific_values):
+        return LD_PowerRail(viewer, powerrail_type, id, 
+                                    specific_values["connectors"])
+    return powerRailCreationFunction
+
+CONTACT_TYPES = {(True, "none"): CONTACT_REVERSE,
+                 (False, "rising"): CONTACT_RISING,
+                 (False, "falling"): CONTACT_FALLING}
+
+def contactCreationFunction(viewer, id, specific_values):
+    contact_type = CONTACT_TYPES.get((specific_values.get("negated", False), 
+                                      specific_values.get("edge", "none")),
+                                     CONTACT_NORMAL)
+    return LD_Contact(viewer, contact_type, specific_values["name"], id)
+
+COIL_TYPES = {(True, "none", "none"): COIL_REVERSE,
+              (False, "none", "set"): COIL_SET,
+              (False, "none", "reset"): COIL_RESET,
+              (False, "rising", "none"): COIL_RISING,
+              (False, "falling", "none"): COIL_FALLING}
+
+def coilCreationFunction(viewer, id, specific_values):
+    coil_type = COIL_TYPES.get((specific_values.get("negated", False), 
+                                specific_values.get("edge", "none"),
+                                specific_values.get("storage", "none")),
+                               COIL_NORMAL)
+    return LD_Coil(viewer, coil_type, specific_values["name"], id)
+
+def stepCreationFunction(viewer, id, specific_values):
+    step = SFC_Step(viewer, specific_values["name"], 
+                            specific_values.get("initial", False), id)
+    if specific_values.get("action", None):
+        step.AddAction()
+        connector = step.GetActionConnector()
+        connector.SetPosition(wx.Point(*specific_values["action"]["position"]))
+    return step
+
+def transitionCreationFunction(viewer, id, specific_values):
+    transition = SFC_Transition(viewer, specific_values["condition_type"], 
+                                        specific_values.get("condition", None), 
+                                        specific_values["priority"], id)
+    return transition
+
+def GetDivergenceCreationFunction(divergence_type):
+    def divergenceCreationFunction(viewer, id, specific_values):
+        return SFC_Divergence(viewer, divergence_type, 
+                                      specific_values["connectors"], id)
+    return divergenceCreationFunction
+
+def jumpCreationFunction(viewer, id, specific_values):
+    return SFC_Jump(viewer, specific_values["target"], id)
+
+def actionBlockCreationFunction(viewer, id, specific_values):
+    return SFC_ActionBlock(viewer, specific_values["actions"], id)
+
+ElementCreationFunctions = {
+    "input": GetVariableCreationFunction(INPUT),
+    "output": GetVariableCreationFunction(OUTPUT),
+    "inout": GetVariableCreationFunction(INOUT),
+    "connector": GetConnectorCreationFunction(CONNECTOR),
+    "continuation": GetConnectorCreationFunction(CONTINUATION),
+    "comment": commentCreationFunction,
+    "leftPowerRail": GetPowerRailCreationFunction(LEFTRAIL),
+    "rightPowerRail": GetPowerRailCreationFunction(RIGHTRAIL),
+    "contact": contactCreationFunction,
+    "coil": coilCreationFunction,
+    "step": stepCreationFunction, 
+    "transition": transitionCreationFunction,
+    "selectionDivergence": GetDivergenceCreationFunction(SELECTION_DIVERGENCE), 
+    "selectionConvergence": GetDivergenceCreationFunction(SELECTION_CONVERGENCE), 
+    "simultaneousDivergence": GetDivergenceCreationFunction(SIMULTANEOUS_DIVERGENCE), 
+    "simultaneousConvergence": GetDivergenceCreationFunction(SIMULTANEOUS_CONVERGENCE), 
+    "jump": jumpCreationFunction,
+    "actionBlock": actionBlockCreationFunction,
+}
+
 #-------------------------------------------------------------------------------
 #                       Graphic elements Viewer base class
 #-------------------------------------------------------------------------------
@@ -381,7 +477,7 @@
         self.CurrentCursor = 0
         
         # Initialize Block, Wire and Comment numbers
-        self.block_id = self.wire_id = self.comment_id = 0
+        self.wire_id = 0
         
         # Initialize Viewer mode to Selection mode
         self.Mode = MODE_SELECTION
@@ -505,45 +601,43 @@
 #-------------------------------------------------------------------------------
 
     def AddBlock(self, block):
-        self.block_id += 1
-        self.Blocks[block] = self.block_id
+        self.Blocks[block.GetId()] = block
         
     def AddWire(self, wire):
         self.wire_id += 1
         self.Wires[wire] = self.wire_id
         
     def AddComment(self, comment):
-        self.comment_id += 1
-        self.Comments[comment] = self.comment_id
+        self.Comments[comment.GetId()] = comment
 
     def IsBlock(self, block):
-        return self.Blocks.get(block, False)
+        return self.Blocks.get(block.GetId(), False)
         
     def IsWire(self, wire):
         return self.Wires.get(wire, False)
         
     def IsComment(self, comment):
-        return self.Comments.get(comment, False)
+        return self.Comments.get(comment.GetId(), False)
 
     def RemoveBlock(self, block):
-        self.Blocks.pop(block)
+        self.Blocks.pop(block.GetId())
         
     def RemoveWire(self, wire):
         self.Wires.pop(wire)
         
     def RemoveComment(self, comment):
-        self.Comments.pop(comment)
+        self.Comments.pop(comment.GetId())
 
     def GetElements(self, sort_blocks=False, sort_wires=False, sort_comments=False):
-        blocks = self.Blocks.keys()
+        blocks = self.Blocks.values()
         wires = self.Wires.keys()
-        comments = self.Comments.keys()
+        comments = self.Comments.values()
         if sort_blocks:
-            blocks.sort(lambda x, y: cmp(self.Blocks[x], self.Blocks[y]))
+            blocks.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
         if sort_wires:
             wires.sort(lambda x, y: cmp(self.Wires[x], self.Wires[y]))
         if sort_comments:
-            comments.sort(lambda x, y: cmp(self.Comments[x], self.Comments[y]))
+            comments.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
         return blocks + wires + comments
 
     def RefreshVisibleElements(self, xp = None, yp = None):
@@ -555,11 +649,11 @@
         width, height = self.GetClientSize()
         screen = wx.Rect(int(x / self.ViewScale[0]), int(y / self.ViewScale[1]),
                          int(width / self.ViewScale[0]), int(height / self.ViewScale[1]))
-        for comment in self.Comments:
+        for comment in self.Comments.itervalues():
             comment.TestVisible(screen)
-        for wire in self.Wires:
+        for wire in self.Wires.iterkeys():
             wire.TestVisible(screen)
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             block.TestVisible(screen)
     
     def GetElementIECPath(self, element):
@@ -604,12 +698,12 @@
     
     def Flush(self):
         self.DeleteDataConsumers()
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             block.Flush()
     
     # Remove all elements
     def CleanView(self):
-        for block in self.Blocks.keys():
+        for block in self.Blocks.itervalues():
             block.Clean()
         self.ResetView()
     
@@ -689,7 +783,7 @@
         pass
 
     # Refresh Viewer elements
-    def RefreshView(self):
+    def RefreshView(self, selection=None):
         self.Inhibit(True)
         self.current_id = 0
         # Start by reseting Viewer
@@ -702,37 +796,19 @@
         while instance is not None:
             instance = self.Controler.GetEditedElementInstanceInfos(self.TagName, exclude = ids, debug = self.Debug)
             if instance is not None:
-                self.loadInstance(instance, ids)
+                self.loadInstance(instance, ids, selection)
         self.RefreshScrollBars()
         
         for wire in self.Wires:
             if not wire.IsConnectedCompatible():
                 wire.SetValid(False)
             if self.Debug:
-                block = wire.EndConnected.GetParentBlock()
-                if isinstance(block, LD_PowerRail):
-                    wire.SetValue(True)
-                if isinstance(block, FBD_Block):
-                    blockname = block.GetName()
-                    connectorname = wire.EndConnected.GetName()
-                    if blockname != "":
-                        iec_path = "%s.%s.%s"%(self.InstancePath, blockname, connectorname)
-                    else:
-                        if connectorname == "":
-                            iec_path = "%s.%s%d"%(self.InstancePath, block.GetType(), block.GetId())
-                        else:
-                            iec_path = "%s.%s%d_%s"%(self.InstancePath, block.GetType(), block.GetId(), connectorname)
-                    if self.AddDataConsumer(iec_path.upper(), wire) is None:
-                        wire.SetValue("undefined")
-                elif isinstance(block, FBD_Variable):
-                    iec_path = "%s.%s"%(self.InstancePath, block.GetName())
-                    if self.AddDataConsumer(iec_path.upper(), wire) is None:
-                        wire.SetValue("undefined")
-                elif isinstance(block, FBD_Connector):
+                iec_path = self.GetElementIECPath(wire)
+                if self.AddDataConsumer(iec_path.upper(), wire) is None:
                     wire.SetValue("undefined")
 
         if self.Debug:
-            for block in self.Blocks.keys():
+            for block in self.Blocks.itervalues():
                 block.SpreadCurrent()
                 iec_path = self.GetElementIECPath(block)
                 if iec_path is not None:
@@ -792,229 +868,46 @@
         self.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
             round(maxx / SCROLLBAR_UNIT) + width_incr, round(maxy / SCROLLBAR_UNIT) + height_incr, 
             xstart, ystart, True)
+    
+    def SelectInGroup(self, element):
+        element.SetSelected(True)
+        if self.SelectedElement is None:
+            self.SelectedElement = element
+        elif isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.SelectElement(element)
+        else:
+            group = Graphic_Group(self)
+            group.SelectElement(self.SelectedElement)
+            group.SelectElement(element)
+            self.SelectedElement = group
         
     # Load instance from given informations
-    def loadInstance(self, instance, ids):
+    def loadInstance(self, instance, ids, selection):
         ids.append(instance["id"])
-        self.current_id = max(self.current_id, instance["id"]) 
-        if instance["type"] == "input":
-            variable = FBD_Variable(self, INPUT, instance["name"], instance["value_type"], instance["id"], instance["executionOrder"])
-            variable.SetPosition(instance["x"], instance["y"])
-            variable.SetSize(instance["width"], instance["height"])
-            self.AddBlock(variable)
-            connectors = variable.GetConnectors()
-            connectors["output"].SetPosition(wx.Point(*instance["connector"]["position"]))
-            if instance["connector"]["negated"]:
-                connectors["output"].SetNegated(True)
-            if instance["connector"]["edge"]:
-                connectors["output"].SetEdge(instance["connector"]["edge"])
-        elif instance["type"] == "output":
-            variable = FBD_Variable(self, OUTPUT, instance["name"], instance["value_type"], instance["id"], instance["executionOrder"])
-            variable.SetPosition(instance["x"], instance["y"])
-            variable.SetSize(instance["width"], instance["height"])
-            self.AddBlock(variable)
-            connectors = variable.GetConnectors()
-            connectors["input"].SetPosition(wx.Point(*instance["connector"]["position"]))
-            if instance["connector"]["negated"]:
-                connectors["input"].SetNegated(True)
-            if instance["connector"]["edge"]:
-                connectors["input"].SetEdge(instance["connector"]["edge"])
-            self.CreateWires(connectors["input"], instance["connector"]["links"], ids)
-        elif instance["type"] == "inout":
-            variable = FBD_Variable(self, INOUT, instance["name"], instance["value_type"], instance["id"], instance["executionOrder"])
-            variable.SetPosition(instance["x"], instance["y"])
-            variable.SetSize(instance["width"], instance["height"])
-            self.AddBlock(variable)
-            connectors = variable.GetConnectors()
-            connectors["output"].SetPosition(wx.Point(*instance["connectors"]["output"]["position"]))
-            connectors["input"].SetPosition(wx.Point(*instance["connectors"]["input"]["position"]))
-            if instance["connectors"]["output"]["negated"]:
-                connectors["output"].SetNegated(True)
-            if instance["connectors"]["output"]["edge"]:
-                connectors["output"].SetEdge(instance["connectors"]["output"]["edge"])
-            if instance["connectors"]["input"]["negated"]:
-                connectors["input"].SetNegated(True)
-            if instance["connectors"]["input"]["edge"]:
-                connectors["input"].SetEdge(instance["connectors"]["input"]["edge"])
-            self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
-        elif instance["type"] == "continuation":
-            connection = FBD_Connector(self, CONTINUATION, instance["name"], instance["id"])
-            connection.SetPosition(instance["x"], instance["y"])
-            connection.SetSize(instance["width"], instance["height"])
-            self.AddBlock(connection)
-            connector = connection.GetConnector()
-            connector.SetPosition(wx.Point(*instance["connector"]["position"]))
-        elif instance["type"] == "connection":
-            connection = FBD_Connector(self, CONNECTOR, instance["name"], instance["id"])
-            connection.SetPosition(instance["x"], instance["y"])
-            connection.SetSize(instance["width"], instance["height"])
-            self.AddBlock(connection)
-            connector = connection.GetConnector()
-            connector.SetPosition(wx.Point(*instance["connector"]["position"]))
-            self.CreateWires(connector, instance["connector"]["links"], ids)
-        elif instance["type"] == "comment":
-            comment = Comment(self, instance["content"], instance["id"])
-            comment.SetPosition(instance["x"], instance["y"])
-            comment.SetSize(instance["width"], instance["height"])
-            self.AddComment(comment)
-        elif instance["type"] == "leftPowerRail":
-            leftpowerrail = LD_PowerRail(self, LEFTRAIL, instance["id"], [True for i in range(len(instance["connectors"]))])
-            leftpowerrail.SetPosition(instance["x"], instance["y"])
-            leftpowerrail.SetSize(instance["width"], instance["height"])
-            self.AddBlock(leftpowerrail)
-            connectors = leftpowerrail.GetConnectors()
-            for i, connector in enumerate(instance["connectors"]):
-                connectors[i].SetPosition(wx.Point(*connector["position"]))
-        elif instance["type"] == "rightPowerRail":
-            rightpowerrail = LD_PowerRail(self, RIGHTRAIL, instance["id"], [True for i in range(len(instance["connectors"]))])
-            rightpowerrail.SetPosition(instance["x"], instance["y"])
-            rightpowerrail.SetSize(instance["width"], instance["height"])
-            self.AddBlock(rightpowerrail)
-            connectors = rightpowerrail.GetConnectors()
-            for i, connector in enumerate(instance["connectors"]):
-                connectors[i].SetPosition(wx.Point(*connector["position"]))
-                self.CreateWires(connectors[i], connector["links"], ids)
-        elif instance["type"] == "contact":
-            if instance["negated"]:
-                negated = instance["negated"]
-            else:
-                negated = False
-            if instance["edge"]:
-                edge = instance["edge"]
-            else:
-                edge = "none"
-            if negated and edge == "none":
-                contact_type = CONTACT_REVERSE
-            elif not negated and edge == "rising":
-                contact_type = CONTACT_RISING
-            elif not negated and edge == "falling":
-                contact_type = CONTACT_FALLING
-            else:
-                contact_type = CONTACT_NORMAL
-            contact = LD_Contact(self, contact_type, instance["name"], instance["id"])
-            contact.SetPosition(instance["x"], instance["y"])
-            contact.SetSize(instance["width"], instance["height"])
-            self.AddBlock(contact)
-            connectors = contact.GetConnectors()
-            connectors["input"].SetPosition(wx.Point(*instance["connectors"]["input"]["position"]))
-            self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
-            connectors["output"].SetPosition(wx.Point(*instance["connectors"]["output"]["position"]))
-        elif instance["type"] == "coil":
-            if instance["negated"]:
-                negated = instance["negated"]
-            else:
-                negated = False
-            if instance["storage"]:
-                storage = instance["storage"]
-            else:
-                storage = "none"
-            if instance["edge"]:
-                edge = instance["edge"]
-            else:
-                edge = "none"
-            if negated and storage == "none" and edge == "none":
-                coil_type = COIL_REVERSE
-            elif not negated and edge == "none" and storage == "set":
-                coil_type = COIL_SET
-            elif not negated and edge == "none" and storage == "reset":
-                coil_type = COIL_RESET
-            elif not negated and storage == "none" and edge == "rising":
-                coil_type = COIL_RISING
-            elif not negated and storage == "none" and edge == "falling":
-                coil_type = COIL_FALLING
-            else:
-                coil_type = COIL_NORMAL
-            coil = LD_Coil(self, coil_type, instance["name"], instance["id"])
-            coil.SetPosition(instance["x"], instance["y"])
-            coil.SetSize(instance["width"], instance["height"])
-            self.AddBlock(coil)
-            connectors = coil.GetConnectors()
-            connectors["input"].SetPosition(wx.Point(*instance["connectors"]["input"]["position"]))
-            self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
-            connectors["output"].SetPosition(wx.Point(*instance["connectors"]["output"]["position"]))
-        elif instance["type"] == "step":
-            if instance["initial"]:
-                initial = instance["initial"]
-            else:
-                initial = False
-            step = SFC_Step(self, instance["name"], initial, instance["id"])
-            step.SetPosition(instance["x"], instance["y"])
-            step.SetSize(instance["width"], instance["height"])
-            self.AddBlock(step)
-            if "output" in instance["connectors"]:
-                step.AddOutput()
-            if "action" in instance["connectors"]:
-                step.AddAction()
-            connectors = step.GetConnectors()
-            if connectors["input"]:
-                connectors["input"].SetPosition(wx.Point(*instance["connectors"]["input"]["position"]))
-                self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
-            if connectors["output"]:
-                connectors["output"].SetPosition(wx.Point(*instance["connectors"]["output"]["position"]))
-            if connectors["action"]:
-                connectors["action"].SetPosition(wx.Point(*instance["connectors"]["action"]["position"]))
-        elif instance["type"] == "transition":
-            transition = SFC_Transition(self, instance["condition_type"], instance["condition"], instance["priority"], instance["id"])
-            transition.SetPosition(instance["x"], instance["y"])
-            transition.SetSize(instance["width"], instance["height"])
-            self.AddBlock(transition)
-            connectors = transition.GetConnectors()
-            connectors["input"].SetPosition(wx.Point(*instance["connectors"]["input"]["position"]))
-            self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
-            connectors["output"].SetPosition(wx.Point(*instance["connectors"]["output"]["position"]))
-            if instance["condition_type"] == "connection":
-                self.CreateWires(connectors["connection"], instance["connectors"]["connection"]["links"], ids)
-        elif instance["type"] in ["selectionDivergence", "selectionConvergence", "simultaneousDivergence", "simultaneousConvergence"]:
-            if instance["type"] == "selectionDivergence":
-                divergence = SFC_Divergence(self, SELECTION_DIVERGENCE, 
-                    len(instance["connectors"]["outputs"]), instance["id"])
-            elif instance["type"] == "selectionConvergence":
-                divergence = SFC_Divergence(self, SELECTION_CONVERGENCE, 
-                    len(instance["connectors"]["inputs"]), instance["id"])
-            elif instance["type"] == "simultaneousDivergence":
-                divergence = SFC_Divergence(self, SIMULTANEOUS_DIVERGENCE, 
-                    len(instance["connectors"]["outputs"]), instance["id"])
-            else:
-                divergence = SFC_Divergence(self, SIMULTANEOUS_CONVERGENCE, 
-                    len(instance["connectors"]["inputs"]), instance["id"])
-            divergence.SetPosition(instance["x"], instance["y"])
-            divergence.SetSize(instance["width"], instance["height"])
-            self.AddBlock(divergence)
-            connectors = divergence.GetConnectors()
-            for i, input_connector in enumerate(instance["connectors"]["inputs"]):
-                connector = connectors["inputs"][i]
-                connector.SetPosition(wx.Point(*input_connector["position"]))
-                self.CreateWires(connector, input_connector["links"], ids)
-            for i, output_connector in enumerate(instance["connectors"]["outputs"]):
-                connector = connectors["outputs"][i]
-                connector.SetPosition(wx.Point(*output_connector["position"]))
-        elif instance["type"] == "jump":
-            jump = SFC_Jump(self, instance["target"], instance["id"])
-            jump.SetPosition(instance["x"], instance["y"])
-            jump.SetSize(instance["width"], instance["height"])
-            self.AddBlock(jump)
-            connector = jump.GetConnector()
-            connector.SetPosition(wx.Point(*instance["connector"]["position"]))
-            self.CreateWires(connector, instance["connector"]["links"], ids)
-        elif instance["type"] == "actionBlock":
-            actionBlock = SFC_ActionBlock(self, instance["actions"], instance["id"])
-            actionBlock.SetPosition(instance["x"], instance["y"])
-            actionBlock.SetSize(instance["width"], instance["height"])
-            self.AddBlock(actionBlock)
-            connector = actionBlock.GetConnector()
-            connector.SetPosition(wx.Point(*instance["connector"]["position"]))
-            self.CreateWires(connector, instance["connector"]["links"], ids)
+        self.current_id = max(self.current_id, instance["id"])
+        creation_function = ElementCreationFunctions.get(instance["type"], None)
+        connectors = {"inputs" : [], "outputs" : []}
+        specific_values = instance["specific_values"]
+        if creation_function is not None:
+            element = creation_function(self, instance["id"], specific_values)
+            if isinstance(element, SFC_Step):
+                if len(instance["inputs"]) > 0:
+                    element.AddInput()
+                if len(instance["outputs"]) > 0:
+                    element.AddOutput()
+            if isinstance(element, SFC_Transition) and specific_values["condition_type"] == "connection":
+                connector = element.GetConditionConnector()
+                self.CreateWires(connector, id, specific_values["connection"]["links"], ids, selection)
         else:
-            connectors = {"inputs" : [], "outputs" : []}
             executionControl = False
-            for input in instance["connectors"]["inputs"]:
+            for input in instance["inputs"]:
                 if input["negated"]:
                     connectors["inputs"].append((input["name"], None, "negated"))
                 elif input["edge"]:
                     connectors["inputs"].append((input["name"], None, input["edge"]))
                 else:
                     connectors["inputs"].append((input["name"], None, "none"))
-            for output in instance["connectors"]["outputs"]:
+            for output in instance["outputs"]:
                 if output["negated"]:
                     connectors["outputs"].append((output["name"], None, "negated"))
                 elif output["edge"]:
@@ -1022,47 +915,52 @@
                 else:
                     connectors["outputs"].append((output["name"], None, "none"))
             if len(connectors["inputs"]) > 0 and connectors["inputs"][0][0] == "EN":
-		connectors["inputs"].pop(0)
-	        executionControl = True
+                connectors["inputs"].pop(0)
+                executionControl = True
             if len(connectors["outputs"]) > 0 and connectors["outputs"][0][0] == "ENO":
                 connectors["outputs"].pop(0)
                 executionControl = True
-            if instance["name"] is None:
-                instance["name"] = ""
-            block = FBD_Block(self, instance["type"], instance["name"], 
-                    instance["id"], len(connectors["inputs"]), 
-                    connectors=connectors, executionControl=executionControl, 
-                    executionOrder=instance["executionOrder"])
-            block.SetPosition(instance["x"], instance["y"])
-            block.SetSize(instance["width"], instance["height"])
-            self.AddBlock(block)
-            connectors = block.GetConnectors()
-            for i, input_connector in enumerate(instance["connectors"]["inputs"]):
-                if i < len(connectors["inputs"]):
-                    connector = connectors["inputs"][i]
-                    connector.SetPosition(wx.Point(*input_connector["position"]))
-                    if input_connector["negated"]:
-                        connector.SetNegated(True)
-                    if input_connector["edge"] != "none":
-                        connector.SetEdge(input_connector["edge"])
-                    self.CreateWires(connector, input_connector["links"], ids)
-            for i, output_connector in enumerate(instance["connectors"]["outputs"]):
-                if i < len(connectors["outputs"]):
-                    connector = connectors["outputs"][i]
-                    if output_connector["negated"]:
-                        connector.SetNegated(True)
-                    if output_connector["edge"] != "none":
-                        connector.SetEdge(output_connector["edge"])
-                    connector.SetPosition(wx.Point(*output_connector["position"]))
-    
-    def CreateWires(self, start_connector, links, ids):
+            if specific_values["name"] is None:
+                specific_values["name"] = ""
+            element = FBD_Block(self, instance["type"], specific_values["name"], 
+                      instance["id"], len(connectors["inputs"]), 
+                      connectors=connectors, executionControl=executionControl, 
+                      executionOrder=specific_values["executionOrder"])
+        element.SetPosition(instance["x"], instance["y"])
+        element.SetSize(instance["width"], instance["height"])
+        if isinstance(element, Comment):
+            self.AddComment(element)
+        else:
+            self.AddBlock(element)
+            connectors = element.GetConnectors()
+        for i, input_connector in enumerate(instance["inputs"]):
+            if i < len(connectors["inputs"]):
+                connector = connectors["inputs"][i]
+                connector.SetPosition(wx.Point(*input_connector["position"]))
+                if input_connector.get("negated", False):
+                    connector.SetNegated(True)
+                if input_connector.get("edge", "none") != "none":
+                    connector.SetEdge(input_connector["edge"])
+                self.CreateWires(connector, instance["id"], input_connector["links"], ids, selection)
+        for i, output_connector in enumerate(instance["outputs"]):
+            if i < len(connectors["outputs"]):
+                connector = connectors["outputs"][i]
+                if output_connector.get("negated", False):
+                    connector.SetNegated(True)
+                if output_connector.get("edge", "none") != "none":
+                    connector.SetEdge(output_connector["edge"])
+                connector.SetPosition(wx.Point(*output_connector["position"]))
+        if selection is not None and selection[0].get(instance["id"], False):
+            self.SelectInGroup(element)
+
+    def CreateWires(self, start_connector, id, links, ids, selection=None):
         for link in links:
             refLocalId = link["refLocalId"]
             if refLocalId is not None:
                 if refLocalId not in ids:
                     new_instance = self.Controler.GetEditedElementInstanceInfos(self.TagName, refLocalId, debug = self.Debug)
                     if new_instance is not None:
-                        self.loadInstance(new_instance, ids)
+                        self.loadInstance(new_instance, ids, selection)
                 connected = self.FindElementById(refLocalId)
                 if connected is not None:
                     points = link["points"]
@@ -1075,6 +973,10 @@
                         wire.ConnectStartPoint(None, start_connector)
                         wire.ConnectEndPoint(None, end_connector)
                         self.AddWire(wire)
+                        if selection is not None and (\
+                           selection[1].get((id, refLocalId), False) or \
+                           selection[1].get((refLocalId, id), False)):
+                            self.SelectInGroup(wire)
 
     def IsOfType(self, type, reference):
         return self.Controler.IsOfType(type, reference, self.Debug)
@@ -1090,7 +992,7 @@
 #-------------------------------------------------------------------------------
 
     def FindBlock(self, pos):
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             if block.HitTest(pos) or block.TestHandle(pos) != (0, 0):
                 return block
         return None
@@ -1111,19 +1013,19 @@
         return None
     
     def FindBlockConnector(self, pos, direction = None, exclude = None):
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             result = block.TestConnector(pos, direction, exclude)
             if result:
                 return result
         return None
     
     def FindElementById(self, id):
-        for element in self.Blocks:
-            if element.GetId() == id:
-                return element
-        for element in self.Comments:
-            if element.GetId() == id:
-                return element
+        block = self.Blocks.get(id, None)
+        if block is not None:
+            return block
+        comment = self.Comments.get(id, None)
+        if comment is not None:
+            return comment
         return None
     
     def SearchElements(self, bbox):
@@ -1977,7 +1879,7 @@
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
         dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
-        dialog.SetStepNames([block.GetName() for block in self.Blocks if isinstance(block, SFC_Step)])
+        dialog.SetStepNames([block.GetName() for block in self.Blocks.itervalues() if isinstance(block, SFC_Step)])
         dialog.SetMinStepSize((bbox.width, bbox.height))
         if dialog.ShowModal() == wx.ID_OK:
             id = self.GetNewId()
@@ -2049,7 +1951,7 @@
 
     def AddNewJump(self, bbox):
         choices = []
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             if isinstance(block, SFC_Step):
                 choices.append(block.GetName())
         dialog = wx.SingleChoiceDialog(self.ParentWindow, "Add a new jump", "Please choose a target", choices, wx.OK|wx.CANCEL)
@@ -2287,7 +2189,7 @@
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
         dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
-        dialog.SetStepNames([block.GetName() for block in self.Blocks if isinstance(block, SFC_Step) and block.GetName() != step.GetName()])
+        dialog.SetStepNames([block.GetName() for block in self.Blocks.itervalues() if isinstance(block, SFC_Step) and block.GetName() != step.GetName()])
         dialog.SetMinStepSize(step.GetSize())
         values = {"name" : step.GetName()}
         connectors = step.GetConnectors()
@@ -2340,7 +2242,7 @@
 
     def EditJumpContent(self, jump):
         choices = []
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             if isinstance(block, SFC_Step):
                 choices.append(block.GetName())
         dialog = wx.SingleChoiceDialog(self.ParentWindow, "Edit jump target", "Please choose a target", choices, wx.OK|wx.CANCEL)
@@ -2474,6 +2376,7 @@
         infos["x"], infos["y"] = step.GetPosition()
         infos["width"], infos["height"] = step.GetSize()
         infos["connectors"] = step.GetConnectors()
+        infos["action"] = step.GetActionConnector()
         self.Controler.SetEditedElementStepInfos(self.TagName, stepid, infos)
 
     def RefreshTransitionModel(self, transition):
@@ -2485,6 +2388,7 @@
         infos["x"], infos["y"] = transition.GetPosition()
         infos["width"], infos["height"] = transition.GetSize()
         infos["connectors"] = transition.GetConnectors()
+        infos["connection"] = transition.GetConditionConnector()
         self.Controler.SetEditedElementTransitionInfos(self.TagName, transitionid, infos)
 
     def RefreshDivergenceModel(self, divergence):
@@ -2535,8 +2439,8 @@
         
     def DeleteVariable(self, variable):
         connectors = variable.GetConnectors()
-        if connectors["output"]:
-            elements = connectors["output"].GetConnectedBlocks()
+        if len(connectors["outputs"]) > 0:
+            elements = connectors["outputs"][0].GetConnectedBlocks()
         else:
             elements = []
         variable.Clean()
@@ -2570,7 +2474,7 @@
 
     def DeleteContact(self, contact):
         connectors = contact.GetConnectors()
-        elements = connectors["output"].GetConnectedBlocks()
+        elements = connectors["outputs"][0].GetConnectedBlocks()
         contact.Clean()
         self.RemoveBlock(contact)
         self.Controler.RemoveEditedElementInstance(self.TagName, contact.GetId())
@@ -2579,7 +2483,7 @@
 
     def DeleteCoil(self, coil):
         connectors = coil.GetConnectors()
-        elements = connectors["output"].GetConnectedBlocks()
+        elements = connectors["outputs"][0].GetConnectedBlocks()
         coil.Clean()
         self.RemoveBlock(coil)
         self.Controler.RemoveEditedElementInstance(self.TagName, coil.GetId())
@@ -2589,7 +2493,8 @@
     def DeletePowerRail(self, powerrail):
         elements = []
         if powerrail.GetType() == LEFTRAIL:
-            for connector in powerrail.GetConnectors():
+            connectors = powerrail.GetConnectors()
+            for connector in connectors["outputs"]:
                 for element in connector.GetConnectedBlocks():
                     if element not in elements:
                         elements.append(element)
@@ -2602,12 +2507,13 @@
     def DeleteStep(self, step):
         elements = []
         connectors = step.GetConnectors()
-        if connectors["output"]:
-            for element in connectors["output"].GetConnectedBlocks():
+        action_connector = step.GetActionConnector()
+        if len(connectors["outputs"]) > 0:
+            for element in connectors["outputs"][0].GetConnectedBlocks():
                 if element not in elements:
                     elements.append(element)
-        if connectors["action"]:
-            for element in connectors["action"].GetConnectedBlocks():
+        if action_connector is not None:
+            for element in action_connector.GetConnectedBlocks():
                 if element not in elements:
                     elements.append(element)
         step.Clean()
@@ -2619,10 +2525,9 @@
     def DeleteTransition(self, transition):
         elements = []
         connectors = transition.GetConnectors()
-        if connectors["output"]:
-            for element in connectors["output"].GetConnectedBlocks():
-                if element not in elements:
-                    elements.append(element)
+        for element in connectors["outputs"][0].GetConnectedBlocks():
+            if element not in elements:
+                elements.append(element)
         transition.Clean()
         self.RemoveBlock(transition)
         self.Controler.RemoveEditedElementInstance(self.TagName, transition.GetId())
@@ -2897,18 +2802,18 @@
                             int((xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[1]), ystart * SCROLLBAR_UNIT + y + 1)
         
         # Draw all elements
-        for comment in self.Comments:
+        for comment in self.Comments.itervalues():
             if comment != self.SelectedElement and (comment.IsVisible() or printing):
                 comment.Draw(dc)
-        for wire in self.Wires:
+        for wire in self.Wires.iterkeys():
             if wire != self.SelectedElement and (wire.IsVisible() or printing):
                  if not self.Debug or wire.GetValue() != True:
                     wire.Draw(dc)
         if self.Debug:
-            for wire in self.Wires:
+            for wire in self.Wires.iterkeys():
                 if wire != self.SelectedElement and (wire.IsVisible() or printing) and wire.GetValue() == True:
                     wire.Draw(dc)
-        for block in self.Blocks:
+        for block in self.Blocks.itervalues():
             if block != self.SelectedElement and (block.IsVisible() or printing):
                 block.Draw(dc)