Adding optimization on redrawing
authorlbessard
Wed, 18 Jul 2007 11:51:30 +0200
changeset 42 4a8400732001
parent 41 0688db995ddf
child 43 4a7e80513edd
Adding optimization on redrawing
Dialogs.py
LDViewer.py
PLCControler.py
PLCOpenEditor.py
SFCViewer.py
Viewer.py
graphics/FBD_Objects.py
graphics/GraphicCommons.py
graphics/LD_Objects.py
graphics/SFC_Objects.py
--- a/Dialogs.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/Dialogs.py	Wed Jul 18 11:51:30 2007 +0200
@@ -110,6 +110,7 @@
               name='Preview', parent=self.MainPanel, pos=wx.Point(274, 104),
               size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wxColour(255,255,255))
+        setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
 
         self._init_sizers()
 
@@ -130,7 +131,6 @@
         if root.IsOk():
             pydata = self.TypeTree.GetPyData(root)
             if inputs and "inputs" in pydata:
-                print inputs, pydata["inputs"]
                 same_inputs = pydata["inputs"] == inputs
             else:
                 same_inputs = True
@@ -340,6 +340,7 @@
               name='Preview', parent=self.MainPanel, pos=wx.Point(24, 170),
               size=wx.Size(350, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wxColour(255,255,255))
+        setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
 
         self._init_sizers()
 
@@ -551,6 +552,7 @@
               name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48),
               size=wx.Size(150, 100), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wxColour(255,255,255))
+        setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
 
         self._init_sizers()
 
@@ -698,6 +700,7 @@
               name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48),
               size=wx.Size(150, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wxColour(255,255,255))
+        setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
 
         self._init_sizers()
 
@@ -869,6 +872,7 @@
               name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48),
               size=wx.Size(150, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wxColour(255,255,255))
+        setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
 
         self._init_sizers()
 
@@ -1135,6 +1139,7 @@
               name='Preview', parent=self.MainPanel, pos=wx.Point(250, 48),
               size=wx.Size(225, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wxColour(255,255,255))
+        setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
 
         self._init_sizers()
 
@@ -1522,7 +1527,6 @@
     def GetValues(self):
         values = []
         for data in self.Table.GetData():
-            print data
             action = {"qualifier" : data["Qualifier"], "value" : data["Value"]}
             if data["Type"] in ["Action", "Variable"]:
                 action["type"] = "reference"
@@ -1590,3 +1594,5 @@
     def SetStepNames(self, step_names):
         self.StepNames = [step_name.upper() for step_name in step_names]
 
+    def GetValue(self):
+        return self.GetSizer().GetItem(1).GetWindow().GetValue()
--- a/LDViewer.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/LDViewer.py	Wed Jul 18 11:51:30 2007 +0200
@@ -173,7 +173,7 @@
     def __init__(self, parent, window, controler):
         Viewer.__init__(self, parent, window, controler)
         self.Rungs = []
-        self.Comments = []
+        self.RungComments = []
 
 #-------------------------------------------------------------------------------
 #                          Refresh functions
@@ -183,12 +183,12 @@
         Viewer.RefreshView(self)
         for i, rung in enumerate(self.Rungs):
             bbox = rung.GetBoundingBox()
-            if i < len(self.Comments):
-                pos = self.Comments[i].GetPosition()
+            if i < len(self.RungComments):
+                pos = self.RungComments[i].GetPosition()
                 if pos[1] > bbox.y:
-                    self.Comment.insert(i, None)
+                    self.RungComments.insert(i, None)
             else:
-                self.Comment.insert(i, None)
+                self.RungComments.insert(i, None)
     
     def loadInstance(self, instance, ids):
         Viewer.loadInstance(self, instance, ids)
@@ -232,14 +232,14 @@
             pos = element.GetPosition()
             i = 0
             inserted = False
-            while i < len(self.Comments) and not inserted: 
-                ipos = self.Comments[i].GetPosition()
+            while i < len(self.RungComments) and not inserted: 
+                ipos = self.RungComments[i].GetPosition()
                 if pos[1] < ipos[1]:
-                    self.Comments.insert(i, element)
+                    self.RungComments.insert(i, element)
                     inserted = True
                 i += 1
             if not inserted:
-                self.Comments.append(element)
+                self.RungComments.append(element)
 
 #-------------------------------------------------------------------------------
 #                          Search Element functions
@@ -256,7 +256,7 @@
             return Viewer.FindElement(self, pos)
         
         elements = []
-        for element in self.Elements:
+        for element in self.GetElements(sort_wires=True):
             if element.HitTest(pos) or element.TestHandle(pos) != (0, 0):
                 elements.append(element)
         if len(elements) == 1:
@@ -264,7 +264,7 @@
         elif len(elements) > 1:
             group = Graphic_Group(self)
             for element in elements:
-                if element in self.Blocks:
+                if self.IsBlock(element):
                     return element
                 group.SelectElement(element)
             return group
@@ -276,8 +276,7 @@
         
         elements = []
         for element in self.Blocks:
-            element_bbox = element.GetBoundingBox()
-            if element_bbox.x >= bbox.x and element_bbox.y >= bbox.y and element_bbox.x + element_bbox.width <= bbox.x + bbox.width and element_bbox.y + element_bbox.height <= bbox.y + bbox.height:
+            if element.IsInSelection(bbox):
                 elements.append(element)
         return elements
 
@@ -293,24 +292,24 @@
             pos = event.GetLogicalPosition(dc)
             element = self.FindElement(pos)
             if self.SelectedElement:
-                if self.SelectedElement in self.Elements:
+                if not isinstance(self.SelectedElement, Graphic_Group):
                     if self.SelectedElement != element:
-                        if self.SelectedElement in self.Wires:
+                        if self.IsWire(self.SelectedElement):
                             self.SelectedElement.SetSelectedSegment(None)
                         else:
                             self.SelectedElement.SetSelected(False)
                     else:
                         self.SelectedElement = None
-                elif element and element not in self.Elements:
+                elif element and isinstance(element, Graphic_Group):
                     if self.SelectedElement.GetElements() != element.GetElements():
                         for elt in self.SelectedElement.GetElements():
-                            if elt in self.Wires:
+                            if self.IsWire(elt):
                                 elt.SetSelectedSegment(None)
                         self.SelectedElement.SetSelected(False)
                         self.SelectedElement = None
                 else:
                     for elt in self.SelectedElement.GetElements():
-                        if elt in self.Wires:
+                        if self.IsWire(elt):
                             elt.SetSelectedSegment(None)
                     self.SelectedElement.SetSelected(False)
                     self.SelectedElement = None
@@ -338,8 +337,8 @@
                     self.Refresh()
         elif self.Mode == MODE_SELECTION and self.SelectedElement:
             dc = self.GetLogicalDC() 
-            if self.SelectedElement in self.Elements:
-                if self.SelectedElement in self.Wires:
+            if not isinstance(self.SelectedElement, Graphic_Group):
+                if self.IsWire(self.SelectedElement):
                     result = self.SelectedElement.TestSegment(event.GetLogicalPosition(dc), True)
                     if result and result[1] in [EAST, WEST]:
                         self.SelectedElement.SetSelectedSegment(result[0])
@@ -347,7 +346,7 @@
                     self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
             else:
                 for element in self.SelectedElement.GetElements():
-                    if element in self.Wires:
+                    if self.IsWire(element):
                         result = element.TestSegment(event.GetLogicalPosition(dc), True)
                         if result and result[1] in [EAST, WEST]:
                             element.SetSelectedSegment(result[0])
@@ -369,7 +368,7 @@
                 if self.SelectedElement and self.SelectedElement != element:
                     self.SelectedElement.SetSelected(False)
                 self.SelectedElement = element
-                if self.SelectedElement in self.Wires:
+                if self.IsWire(self.SelectedElement):
                     self.SelectedElement.SetSelectedSegment(0)
                 else:
                     self.SelectedElement.SetSelected(True)
@@ -390,6 +389,8 @@
     def OnViewerMotion(self, event):
         if self.GetDrawingMode() == FREEDRAWING_MODE:
             Viewer.OnViewerMotion(self, event)
+        elif self.rubberBand.IsShown():
+            self.rubberBand.OnMotion(event, self.GetLogicalDC(), self.Scaling)
         event.Skip()
 
 #-------------------------------------------------------------------------------
@@ -402,14 +403,14 @@
         else:
             keycode = event.GetKeyCode()
             if keycode == WXK_DELETE and self.SelectedElement:
-                if self.SelectedElement in self.Blocks:
+                if self.IsBlock(self.SelectedElement):
                     self.SelectedElement.Delete()
-                elif self.SelectedElement in self.Wires:
+                elif self.IsWire(self.SelectedElement):
                     self.DeleteWire(self.SelectedElement)
-                elif self.SelectedElement not in self.Elements:
+                elif isinstance(self.SelectedElement, Graphic_Group):
                     all_wires = True
                     for element in self.SelectedElement.GetElements():
-                        all_wires &= element in self.Wires
+                        all_wires &= self.IsWire(element)
                     if all_wires:
                         self.DeleteWire(self.SelectedElement)
                     else:
@@ -421,7 +422,7 @@
 #                          Adding element functions
 #-------------------------------------------------------------------------------
 
-    def AddRung(self):
+    def AddLadderRung(self):
         dialog = LDElementDialog(self.Parent, "coil")
         varlist = []
         vars = self.Controler.GetCurrentElementEditingInterfaceVars()
@@ -447,8 +448,8 @@
             comment = Comment(self, "Commentaire", id)
             comment.SetPosition(startx, starty)
             comment.SetSize(LD_COMMENT_DEFAULTSIZE[0], LD_COMMENT_DEFAULTSIZE[1])
-            self.Elements.append(comment)
-            self.Comments.append(comment)
+            self.AddComment(comment)
+            self.RungComments.append(comment)
             self.Controler.AddCurrentElementEditingComment(id)
             self.RefreshCommentModel(comment)
             starty += LD_COMMENT_DEFAULTSIZE[1] + LD_OFFSET[1]
@@ -456,8 +457,7 @@
             id = self.GetNewId()
             leftpowerrail = LD_PowerRail(self, LEFTRAIL, id)
             leftpowerrail.SetPosition(startx, starty)
-            self.Elements.append(leftpowerrail)
-            self.Blocks.append(leftpowerrail)
+            self.AddBlock(leftpowerrail)
             rung.SelectElement(leftpowerrail)
             self.Controler.AddCurrentElementEditingPowerRail(id, LEFTRAIL)
             self.RefreshPowerRailModel(leftpowerrail)
@@ -465,8 +465,7 @@
             id = self.GetNewId()
             coil = LD_Coil(self, values["type"], values["name"], id)
             coil.SetPosition(startx, starty + (LD_LINE_SIZE - LD_ELEMENT_SIZE[1]) / 2)
-            self.Elements.append(coil)
-            self.Blocks.append(coil)
+            self.AddBlock(coil)
             rung.SelectElement(coil)
             self.Controler.AddCurrentElementEditingCoil(id)
             # Create Wire between LeftPowerRail and Coil
@@ -477,15 +476,13 @@
             end_connector.Connect((wire, -1), False)
             wire.ConnectStartPoint(None, start_connector)
             wire.ConnectEndPoint(None, end_connector)
-            self.Wires.append(wire)
-            self.Elements.append(wire)
+            self.AddWires(wire)
             rung.SelectElement(wire)
             # Create RightPowerRail
             id = self.GetNewId()
             rightpowerrail = LD_PowerRail(self, RIGHTRAIL, id)
             rightpowerrail.SetPosition(startx, starty)
-            self.Elements.append(rightpowerrail)
-            self.Blocks.append(rightpowerrail)
+            self.AddBlock(rightpowerrail)
             rung.SelectElement(rightpowerrail)
             self.Controler.AddCurrentElementEditingPowerRail(id, RIGHTRAIL)
             # Create Wire between LeftPowerRail and Coil
@@ -496,21 +493,20 @@
             end_connector.Connect((wire, -1), False)
             wire.ConnectStartPoint(None, start_connector)
             wire.ConnectEndPoint(None, end_connector)
-            self.Wires.append(wire)
-            self.Elements.append(wire)
+            self.AddWires(wire)
             rung.SelectElement(wire)
             self.RefreshPosition(coil)
             self.Rungs.append(rung)
             self.Refresh()
 
-    def AddContact(self):
+    def AddLadderContact(self):
         wires = []
-        if self.SelectedElement in self.Wires:
+        if self.IsWire(self.SelectedElement):
             left_element = self.SelectedElement.EndConnected
             if not isinstance(left_element.GetParentBlock(), LD_Coil):
                 wires.append(self.SelectedElement)
-        elif self.SelectedElement and self.SelectedElement not in self.Elements:
-            if False not in [element in self.Wires for element in self.SelectedElement.GetElements()]:
+        elif self.SelectedElement and isinstance(self.SelectedElement,Graphic_Group):
+            if False not in [self.IsWire(element) for element in self.SelectedElement.GetElements()]:
                 for element in self.SelectedElement.GetElements():
                     wires.append(element)
         if len(wires) > 0:
@@ -529,8 +525,7 @@
                 id = self.GetNewId()
                 contact = LD_Contact(self, values["type"], values["name"], id)
                 contact.SetPosition(0, points[0].y - (LD_ELEMENT_SIZE[1] + 1) / 2)
-                self.Elements.append(contact)
-                self.Blocks.append(contact)
+                self.AddBlock(contact)
                 self.Controler.AddCurrentElementEditingContact(id)
                 rungindex = self.FindRung(wires[0])
                 rung = self.Rungs[rungindex]
@@ -557,8 +552,7 @@
                     wire.SetSelectedSegment(None)
                     wire.Clean()
                     rung.SelectElement(wire)
-                    self.Wires.remove(wire)
-                    self.Elements.remove(wire)
+                    self.RemoveWire(wire)
                 wires = []
                 right_wires = []
                 for i, left_element in enumerate(left_elements):
@@ -578,8 +572,7 @@
                     wire.ConnectEndPoint(None, connectors["output"])
                 right_wires.reverse()
                 for wire in wires:
-                    self.Wires.append(wire)
-                    self.Elements.append(wire)
+                    self.AddWire(wire)
                     rung.SelectElement(wire)
                 self.RefreshPosition(contact)
                 if len(right_wires) > 1:
@@ -601,11 +594,11 @@
             message.ShowModal()
             message.Destroy()
 
-    def AddBranch(self):
+    def AddLadderBranch(self):
         blocks = []
-        if self.SelectedElement in self.Blocks:
+        if self.IsBlock(self.SelectedElement):
             blocks = [self.SelectedElement]
-        elif self.SelectedElement not in self.Elements:
+        elif isinstance(self.SelectedElement, Graphic_Group):
             elements = self.SelectedElement.GetElements()
             for element in elements:
                 blocks.append(element)
@@ -764,8 +757,7 @@
                             coil = LD_Coil(self, values["type"], values["name"], id)
                             pos = blocks[0].GetPosition()
                             coil.SetPosition(pos[0], pos[1] + LD_LINE_SIZE)
-                            self.Elements.append(coil)
-                            self.Blocks.append(coil)
+                            self.AddBlock(coil)
                             rung.SelectElement(coil)
                             self.Controler.AddCurrentElementEditingCoil(id)
                             coil_connectors = coil.GetConnectors()
@@ -775,8 +767,7 @@
                             coil_connectors["output"].Connect((wire, -1), False)
                             wire.ConnectStartPoint(None, connectors[index + 1])
                             wire.ConnectEndPoint(None, coil_connectors["output"])
-                            self.Wires.append(wire)
-                            self.Elements.append(wire)
+                            self.AddWire(wire)
                             rung.SelectElement(wire)
                             left_elements.reverse()
                             for i, left_element in enumerate(left_elements):
@@ -805,8 +796,7 @@
                                     new_wire.ConnectEndPoint(None, left_element)
                     wires.reverse()
                     for wire in wires:
-                        self.Wires.append(wire)
-                        self.Elements.append(wire)
+                        self.AddWire(wire)
                         rung.SelectElement(wire)
                     right_elements.reverse()
                 for block in blocks:
@@ -827,7 +817,7 @@
             message.ShowModal()
             message.Destroy()
 
-    def AddBlock(self):
+    def AddLadderBlock(self):
         message = wxMessageDialog(self, "This option isn't available yet!", "Warning", wxOK|wxICON_EXCLAMATION)
         message.ShowModal()
         message.Destroy()
@@ -851,13 +841,11 @@
             for wire in input_wires:
                 wire.Clean()
                 rung.SelectElement(wire)
-                self.Wires.remove(wire)
-                self.Elements.remove(wire)
+                self.RemoveWire(wire)
             for wire in output_wires:
                 wire.Clean()
                 rung.SelectElement(wire)
-                self.Wires.remove(wire)
-                self.Elements.remove(wire)
+                self.RemoveWire(wire)
             rung.SelectElement(contact)
             contact.Clean()
             left_elements.reverse()
@@ -876,8 +864,7 @@
                             wire_removed.append(wire)
                     for wire in wire_removed:
                         wire.Clean()
-                        self.Wires.remove(wire)
-                        self.Elements.remove(wire)
+                        self.RemoveWire(wire)
                         rung.SelectElement(wire)
             wires = []
             for left_element, left_index in left_elements:
@@ -890,14 +877,12 @@
                     wire.ConnectEndPoint(None, left_element)
             wires.reverse()
             for wire in wires:
-                self.Wires.append(wire)
-                self.Elements.append(wire)
+                self.RemoveWire(wire)
                 rung.SelectElement(wire)
             right_elements.reverse()
             for right_element, right_index in right_elements:
                 self.RefreshPosition(right_element.GetParentBlock())
-            self.Blocks.remove(contact)
-            self.Elements.remove(contact)
+            self.RemoveBlock(contact)
             self.Controler.RemoveCurrentElementEditingInstance(contact.GetId())
             rung.RefreshBoundingBox()
             new_bbox = rung.GetBoundingBox()
@@ -912,11 +897,9 @@
         element.Clean()
         for wire in input_wires:
             wire.Clean()
-            self.Wires.remove(wire)
-            self.Elements.remove(wire)
+            self.RemoveWire(wire)
             rung.SelectElement(wire)
-        self.Blocks.remove(element)
-        self.Elements.remove(element)
+        self.RemoveBlock(element)
         self.Controler.RemoveCurrentElementEditingInstance(element.GetId())
         for left_element in left_elements:
             block = left_element.GetParentBlock()
@@ -962,18 +945,16 @@
                 self.RecursiveDeletion(coil, rung)
             else:
                 for element in rung.GetElements():
-                    if element in self.Wires:
+                    if self.IsWire(element):
                         element.Clean()
-                        self.Wires.remove(element)
-                        self.Elements.remove(element)
+                        self.RemoveWire(element)
                 for element in rung.GetElements():
-                    if element in self.Blocks:
+                    if self.IsBlock(element):
                         self.Controler.RemoveCurrentElementEditingInstance(element.GetId())
-                        self.Blocks.remove(element)
-                        self.Elements.remove(element)
+                        self.RemoveBlock(element)
                 self.Controler.RemoveCurrentElementEditingInstance(self.Comments[rungindex].GetId())
-                self.Elements.remove(self.Comments[rungindex])
-                self.Comments.pop(rungindex)
+                self.RemoveComment(self.RungComments[rungindex])
+                self.RungComments.pop(rungindex)
                 self.Rungs.pop(rungindex)
                 if rungindex < len(self.Rungs):
                     next_bbox = self.Rungs[rungindex].GetBoundingBox()
@@ -987,11 +968,11 @@
             wires = []
             left_elements = []
             right_elements = []
-            if wire in self.Wires:
+            if self.IsWire(wire):
                 wires = [wire]
-            elif wire not in self.Elements:
+            elif isinstance(wire, Graphic_Group):
                 for element in wire.GetElements():
-                    if element in self.Wires:
+                    if self.IsWire(element):
                         wires.append(element)
                     else:
                         wires = []
@@ -1009,8 +990,7 @@
                         right_elements.append(wire.StartConnected)
                     if connections == (False, False) or connections == (False, True) and isinstance(left_block, LD_PowerRail):
                         wire.Clean()
-                        self.Wires.remove(wire)
-                        self.Elements.remove(wire)
+                        self.RemoveWire(wire)
                         rung.SelectElement(wire)
                 for left_element in left_elements:
                     left_block = left_element.GetParentBlock()
@@ -1153,11 +1133,11 @@
     def RefreshRungs(self, movey, fromidx):
         if movey != 0:
             for i in xrange(fromidx, len(self.Rungs)):
-                self.Comments[i].Move(0, movey)
-                self.Comments[i].RefreshModel()
+                self.RungComments[i].Move(0, movey)
+                self.RungComments[i].RefreshModel()
                 self.Rungs[i].Move(0, movey)
                 for element in self.Rungs[i].GetElements():
-                    if element in self.Blocks:
+                    if self.IsBlock(element):
                         self.RefreshPosition(element)
 
 #-------------------------------------------------------------------------------
--- a/PLCControler.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/PLCControler.py	Wed Jul 18 11:51:30 2007 +0200
@@ -33,7 +33,7 @@
 from graphics.GraphicCommons import *
 from PLCGenerator import *
 
-duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m)?(?:([0-9]{1,2})s)?(?:([0-9]{1,3})ms)?")
+duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:.[0-9]*)?)ms)?")
 
 [ITEM_UNEDITABLE, ITEM_PROJECT, ITEM_POU, ITEM_CLASS, ITEM_VARIABLE,
  ITEM_TRANSITION, ITEM_ACTION, ITEM_CONFIGURATION, ITEM_RESOURCE] = range(9)
@@ -164,6 +164,7 @@
         self.ProjectBuffer = None
         self.FilePath = ""
         self.FileName = ""
+        self.ProgramFilePath = ""
         self.ElementsOpened = []
         self.CurrentElementEditing = None
         self.RefreshPouUsingTree()
@@ -222,6 +223,10 @@
     def GetFilePath(self):
         return self.FilePath
     
+    # Return file path if project is an open file
+    def GetProgramFilePath(self):
+        return self.ProgramFilePath
+    
     # Return file name and point out if file is up to date
     def GetFilename(self):
         if self.ProjectBuffer.IsCurrentSaved():
@@ -375,6 +380,7 @@
             programfile = open(filepath, "w")
             programfile.write(program)
             programfile.close()
+            self.ProgramFilePath = filepath
             return True
             #except:
             #    pass
@@ -552,7 +558,6 @@
     
     # Extract varlists from a list of vars
     def ExtractVarLists(self, vars):
-        print "extract varlist"
         varlist_list = []
         current_varlist = None
         current_type = None
@@ -1790,12 +1795,12 @@
             result = duration_model.match(task["Interval"]).groups()
             if reduce(lambda x, y: x or y != None, result):
                 values = []
-                for value in result:
+                for value in result[:-1]:
                     if value != None:
                         values.append(int(value))
                     else:
                         values.append(0)
-                values[3] = values[3] * 1000
+                values.append(int(float(result[-1]) * 1000))
                 new_task.setInterval(time(*values))
             new_task.priority.setValue(int(task["Priority"]))
             if task["Name"] != "":
@@ -1834,7 +1839,10 @@
                 if interval.second != 0:
                     text += "%ds"%interval.second
                 if interval.microsecond != 0:
-                    text += "%dms"%(interval.microsecond / 1000)
+                    if interval.microsecond % 1000 != 0:
+                        text += "%.3fms"%(float(interval.microsecond) / 1000)
+                    else:
+                        text += "%dms"%(interval.microsecond / 1000)
                 new_task["Interval"] = text
             else:
                 new_task["Interval"] = ""
--- a/PLCOpenEditor.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/PLCOpenEditor.py	Wed Jul 18 11:51:30 2007 +0200
@@ -557,7 +557,7 @@
         event.Skip()
 
     def OnGenerateProgramMenu(self, event):
-        dialog = wxFileDialog(self, "Choose a file", os.getcwd(), "",  "ST files (*.st)|*.st|All files|*.*", wxSAVE|wxCHANGE_DIR)
+        dialog = wxFileDialog(self, "Choose a file", os.getcwd(), self.Controler.GetProgramFilePath(),  "ST files (*.st)|*.st|All files|*.*", wxSAVE|wxCHANGE_DIR)
         if dialog.ShowModal() == wxID_OK:
             filepath = dialog.GetPath()
             if os.path.isdir(os.path.dirname(filepath)):
@@ -642,7 +642,6 @@
         event.Skip()
     
     def OnBlockTool(self, event):
-        self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARBLOCK)
         selected = self.TabsOpened.GetSelection()
         if selected != -1:
             self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK)
@@ -672,7 +671,7 @@
     def OnRungTool(self, event):
         selected = self.TabsOpened.GetSelection()
         if selected != -1:
-            self.TabsOpened.GetPage(selected).AddRung()
+            self.TabsOpened.GetPage(selected).AddLadderRung()
         event.Skip()
     
     def OnCoilTool(self, event):
@@ -690,13 +689,13 @@
             if self.DrawingMode == FREEDRAWING_MODE:
                 self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT)
             else:
-                self.TabsOpened.GetPage(selected).AddContact()
+                self.TabsOpened.GetPage(selected).AddLadderContact()
         event.Skip()
     
     def OnBranchTool(self, event): 
         selected = self.TabsOpened.GetSelection()
         if selected != -1:
-            self.TabsOpened.GetPage(selected).AddBranch()
+            self.TabsOpened.GetPage(selected).AddLadderBranch()
         event.Skip()    
     
     def OnInitialStepTool(self, event):
--- a/SFCViewer.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/SFCViewer.py	Wed Jul 18 11:51:30 2007 +0200
@@ -41,8 +41,7 @@
         startpoint = [start.GetPosition(False), start.GetDirection()]
         endpoint = [end.GetPosition(False), end.GetDirection()]
         wire = Wire(self, startpoint, endpoint)
-        self.Wires.append(wire)
-        self.Elements.append(wire)
+        self.AddWire(wire)
         start.Connect((wire, 0), False)
         end.Connect((wire, -1), False)
         wire.ConnectStartPoint(None, start)
@@ -62,8 +61,7 @@
         else:
             previous.RefreshOutputPosition()
         wire.SetPoints([wxPoint(pos.x, pos.y + GetWireSize(previous)), wxPoint(pos.x, pos.y)])
-        self.Blocks.append(transition)
-        self.Elements.append(transition)
+        self.AddBlock(transition)
         self.Controler.AddCurrentElementEditingTransition(id)
         self.RefreshTransitionModel(transition)
         if next:
@@ -86,19 +84,16 @@
         input_wire = input_wires[0][0]
         previous = input_wire.EndConnected
         input_wire.Clean()
-        self.Wires.remove(input_wire)
-        self.Elements.remove(input_wire)
+        self.RemoveWire(input_wire)
         output_wires = connectors["output"].GetWires()
         if len(output_wires) != 1:
             return
         output_wire = output_wires[0][0]
         next = output_wire.StartConnected
         output_wire.Clean()
-        self.Wires.remove(output_wire)
-        self.Elements.remove(output_wire)
+        self.RemoveWire(output_wire)
         transition.Clean()
-        self.Blocks.remove(transition)
-        self.Elements.remove(transition)
+        self.RemoveBlock(transition)
         self.Controler.RemoveCurrentElementEditingInstance(transition.GetId())
         wire = self.ConnectConnectors(next, previous)
         return wire
@@ -120,8 +115,7 @@
         else:
             previous.RefreshOutputPosition()
         wire.SetPoints([wxPoint(pos.x, pos.y + GetWireSize(previous)), wxPoint(pos.x, pos.y)])
-        self.Blocks.append(step)
-        self.Elements.append(step)
+        self.AddBlock(step)
         self.Controler.AddCurrentElementEditingStep(id)
         self.RefreshStepModel(step)
         if next:
@@ -145,8 +139,7 @@
             input_wire = input_wires[0][0]
             previous = input_wire.EndConnected
             input_wire.Clean()
-            self.Wires.remove(input_wire)
-            self.Elements.remove(input_wire)
+            self.RemoveWire(input_wire)
         else:
             previous = None
         if connectors["output"]:
@@ -156,16 +149,14 @@
             output_wire = output_wires[0][0]
             next = output_wire.StartConnected
             output_wire.Clean()
-            self.Wires.remove(output_wire)
-            self.Elements.remove(output_wire)
+            self.RemoveWire(output_wire)
         else:
             next = None
         action = step.GetActionConnector()
         if action:
             self.DeleteActionBlock(action.GetParentBlock())
         step.Clean()
-        self.Blocks.remove(step)
-        self.Elements.remove(step)
+        self.RemoveBlock(step)
         self.Controler.RemoveCurrentElementEditingInstance(step.GetId())
         if next and previous:
             wire = self.ConnectConnectors(next, previous)
@@ -185,7 +176,7 @@
             pos = event.GetLogicalPosition(dc)
             if event.ControlDown():
                 element = self.FindElement(pos, True)
-                if element and element not in self.Wires:
+                if element and not self.IsWire(element):
                     if isinstance(self.SelectedElement, Graphic_Group):
                         self.SelectedElement.SelectElement(element)
                     else:
@@ -202,7 +193,7 @@
             else:
                 element = self.FindElement(pos)
                 if self.SelectedElement and self.SelectedElement != element:
-                    if self.SelectedElement in self.Wires:
+                    if self.IsWire(self.SelectedElement):
                         self.SelectedElement.SetSelectedSegment(None)
                     else:
                         self.SelectedElement.SetSelected(False)
@@ -225,8 +216,7 @@
             wire.Handle = (HANDLE_POINT, 0)
             wire.ProcessDragging(0, 0)
             wire.Handle = (HANDLE_POINT, 1)
-            self.Wires.append(wire)
-            self.Elements.append(wire)
+            self.AddWire(wire)
             if self.SelectedElement:
                 self.SelectedElement.SetSelected(False)
             self.SelectedElement = wire
@@ -252,7 +242,7 @@
         elif self.Mode == MODE_INITIALSTEP:
             wxCallAfter(self.AddInitialStep, GetScaledEventPosition(event, self.GetLogicalDC(), self.Scaling))
         elif self.Mode == MODE_SELECTION and self.SelectedElement:
-            if self.SelectedElement in self.Wires:
+            if self.IsWire(self.SelectedElement):
                 self.SelectedElement.SetSelectedSegment(0)
             else:
                 self.SelectedElement.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)
@@ -279,7 +269,7 @@
                 if self.SelectedElement and self.SelectedElement != element:
                     self.SelectedElement.SetSelected(False)
                 self.SelectedElement = element
-                if self.SelectedElement in self.Wires:
+                if self.IsWire(self.SelectedElement):
                     self.SelectedElement.SetSelectedSegment(0)
                 else:
                     self.SelectedElement.SetSelected(True)
@@ -303,7 +293,7 @@
         elif self.rubberBand.IsShown():
             self.rubberBand.OnMotion(event, self.GetLogicalDC(), self.Scaling)
         elif self.Mode == MODE_SELECTION and self.SelectedElement:
-            if self.SelectedElement not in self.Wires:
+            if not self.IsWire(self.SelectedElement):
                 self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling)
             self.Refresh()
         elif self.Mode == MODE_WIRE and self.SelectedElement:
@@ -327,16 +317,35 @@
         if keycode == WXK_DELETE and self.SelectedElement:
             self.SelectedElement.Delete()
             self.SelectedElement = None
-        elif keycode == WXK_LEFT and self.SelectedElement:
-            self.SelectedElement.Move(-scaling[0], 0)
-        elif keycode == WXK_RIGHT and self.SelectedElement:
-            self.SelectedElement.Move(scaling[0], 0)
-        elif keycode == WXK_UP and self.SelectedElement:
-            self.SelectedElement.Move(0, -scaling[1])
-        elif keycode == WXK_DOWN and self.SelectedElement:
-            self.SelectedElement.Move(0, scaling[1])
+        elif keycode == WXK_LEFT:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(0, ypos)
+            elif event.ControlDown():
+                self.Scroll(max(0, xpos - 1), ypos)
+            elif self.SelectedElement:
+                self.SelectedElement.Move(-scaling[0], 0)
+        elif keycode == WXK_RIGHT:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(xmax, ypos)
+            elif event.ControlDown():
+                self.Scroll(min(xpos + 1, xmax), ypos)
+            elif self.SelectedElement:
+                self.SelectedElement.Move(scaling[0], 0)
+        elif keycode == WXK_UP:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(xpos, 0)
+            elif event.ControlDown():
+                self.Scroll(xpos, max(0, ypos - 1))
+            elif self.SelectedElement:
+                self.SelectedElement.Move(0, -scaling[1])
+        elif keycode == WXK_DOWN:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(xpos, ymax)
+            elif event.ControlDown():
+                self.Scroll(xpos, min(ypos + 1, ymax))
+            elif self.SelectedElement:
+                self.SelectedElement.Move(0, scaling[1])
         self.Refresh()
-        event.Skip()
         
 #-------------------------------------------------------------------------------
 #                          Adding element functions
@@ -355,8 +364,7 @@
             step.SetPosition(pos.x, pos.y)
             width, height = step.GetSize()
             step.SetSize(max(min_width, width), max(min_height, height))
-            self.Blocks.append(step)
-            self.Elements.append(step)
+            self.AddBlock(step)
             self.Controler.AddCurrentElementEditingStep(id)
             self.RefreshStepModel(step)
             self.Parent.RefreshProjectTree()
@@ -371,13 +379,12 @@
             dialog.SetStepNames([block.GetName() for block in self.Blocks if isinstance(block, SFC_Step)])
             if dialog.ShowModal() == wxID_OK:
                 name = dialog.GetValue()
-                if self.SelectedElement in self.Wires:
+                if self.IsWire(self.SelectedElement):
                     self.SelectedElement.SetSelectedSegment(None)
                     previous = self.SelectedElement.EndConnected
                     next = self.SelectedElement.StartConnected
                     self.SelectedElement.Clean()
-                    self.Wires.remove(self.SelectedElement)
-                    self.Elements.remove(self.SelectedElement)
+                    self.RemoveWire(self.SelectedElement)
                 else:
                     connectors = self.SelectedElement.GetConnectors()
                     if connectors["output"]:
@@ -388,8 +395,7 @@
                         wire = wires[0][0]
                         next = wire.StartConnected
                         wire.Clean()
-                        self.Wires.remove(wire)
-                        self.Elements.remove(wire)
+                        self.RemoveWire(wire)
                     else:
                         self.SelectedElement.AddOutput()
                         connectors = self.SelectedElement.GetConnectors()
@@ -407,7 +413,7 @@
                     step.RefreshModel()
                     step_connectors = step.GetConnectors()
                     transition = self.CreateTransition(step_connectors["output"], next)
-                if self.SelectedElement in self.Wires:
+                if self.IsWire(self.SelectedElement):
                     self.SelectedElement = wire
                     self.SelectedElement.SetSelectedSegment(0)
                 else:
@@ -439,8 +445,7 @@
                     wire = self.ConnectConnectors(actionblock_connector, connectors["action"])
                     wire.SetPoints([wxPoint(pos.x + SFC_WIRE_MIN_SIZE, pos.y), wxPoint(pos.x, pos.y)])
                     actionblock.SetActions(actions)
-                    self.Blocks.append(actionblock)
-                    self.Elements.append(actionblock)
+                    self.AddBlock(actionblock)
                     self.Controler.AddCurrentElementEditingActionBlock(id)
                     self.RefreshActionBlockModel(actionblock)
                     self.Refresh()
@@ -457,8 +462,7 @@
                         previous = self.SelectedElement.EndConnected
                         next = self.SelectedElement.StartConnected
                         self.SelectedElement.Clean()
-                        self.Wires.remove(self.SelectedElement)
-                        self.Elements.remove(self.SelectedElement)
+                        self.RemoveWire(self.SelectedElement)
                         self.SelectedElement = None
                     elif isinstance(self.SelectedElement, SFC_Step):
                         connectors = self.SelectedElement.GetConnectors()
@@ -470,8 +474,7 @@
                             wire = wires[0][0]
                             next = wire.StartConnected
                             wire.Clean()
-                            self.Wires.remove(wire)
-                            self.Elements.remove(wire)
+                            self.RemoveWire(wire)
                         else:
                             self.SelectedElement.AddOutput()
                             connectors = self.SelectedElement.GetConnectors()
@@ -490,8 +493,7 @@
                     wire = self.ConnectConnectors(divergence_connectors["inputs"][0], previous)
                     previous_block.RefreshOutputPosition()
                     wire.SetPoints([wxPoint(pos.x, pos.y + wire_size), wxPoint(pos.x, pos.y)])
-                    self.Blocks.append(divergence)
-                    self.Elements.append(divergence)
+                    self.AddBlock(divergence)
                     self.Controler.AddCurrentElementEditingDivergence(id, value["type"])
                     self.RefreshDivergenceModel(divergence)
                     for index, connector in enumerate(divergence_connectors["outputs"]):
@@ -515,8 +517,7 @@
                         previous = self.SelectedElement.EndConnected
                         next = self.SelectedElement.StartConnected
                         self.SelectedElement.Clean()
-                        self.Wires.remove(self.SelectedElement)
-                        self.Elements.remove(self.SelectedElement)
+                        self.RemoveWire(self.SelectedElement)
                         self.SelectedElement = None
                     elif isinstance(self.SelectedElement, SFC_Step):
                         connectors = self.SelectedElement.GetConnectors()
@@ -528,8 +529,7 @@
                             wire = wires[0][0]
                             next = wire.StartConnected
                             wire.Clean()
-                            self.Wires.remove(wire)
-                            self.Elements.remove(wire)
+                            self.RemoveWire(wire)
                         else:
                             self.SelectedElement.AddOutput()
                             connectors = self.SelectedElement.GetConnectors()
@@ -551,8 +551,7 @@
                     wire = self.ConnectConnectors(divergence_connectors["inputs"][0], previous)
                     previous_block.RefreshOutputPosition()
                     wire.SetPoints([wxPoint(pos.x, pos.y + wire_size), wxPoint(pos.x, pos.y)])
-                    self.Blocks.append(divergence)
-                    self.Elements.append(divergence)
+                    self.AddBlock(divergence)
                     self.Controler.AddCurrentElementEditingDivergence(id, value["type"])
                     self.RefreshDivergenceModel(divergence)
                     for index, connector in enumerate(divergence_connectors["outputs"]):
@@ -587,8 +586,7 @@
                             wire = wires[0][0]
                             next = wire.StartConnected
                             wire.Clean()
-                            self.Wires.remove(wire)
-                            self.Elements.remove(wire)
+                            self.RemoveWire(wire)
                     inputs = []
                     for input in self.SelectedElement.GetElements():
                         input_connectors = input.GetConnectors()
@@ -624,8 +622,7 @@
                     divergence.RefreshPosition()
                     pos = divergence_connectors["outputs"][0].GetRelPosition()
                     divergence.MoveConnector(divergence_connectors["outputs"][0], - pos.x)
-                    self.Blocks.append(divergence)
-                    self.Elements.append(divergence)
+                    self.AddBlock(divergence)
                     self.Controler.AddCurrentElementEditingDivergence(id, value["type"])
                     self.RefreshDivergenceModel(divergence)
                     if next:
@@ -681,8 +678,7 @@
                 jump = SFC_Jump(self, value, id)
                 pos = transition_connectors["output"].GetPosition(False)
                 jump.SetPosition(pos.x, pos.y + SFC_WIRE_MIN_SIZE)
-                self.Blocks.append(jump)
-                self.Elements.append(jump)
+                self.AddBlock(jump)
                 self.Controler.AddCurrentElementEditingJump(id)
                 jump_connector = jump.GetConnector()
                 wire = self.ConnectConnectors(jump_connector, transition_connectors["output"])
@@ -701,7 +697,7 @@
             comment.SetPosition(bbox.x, bbox.y)
             min_width, min_height = comment.GetMinSize()
             comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height))
-            self.Elements.append(comment)
+            self.AddComment(comment)
             self.Controler.AddCurrentElementEditingComment(id)
             self.RefreshCommentModel(comment)
             self.Refresh()
@@ -801,8 +797,7 @@
                 if next_block:
                     if isinstance(next_block, SFC_Divergence) and next_block.GetType() == SIMULTANEOUS_CONVERGENCE and isinstance(previous_block, SFC_Divergence) and previous_block.GetType() == SIMULTANEOUS_DIVERGENCE:
                         wire.Clean()
-                        self.Wires.remove(wire)
-                        self.Elements.remove(wire)
+                        self.RemoveWire(wire)
                         next_block.RemoveBranch(next)
                         if next_block.GetBranchNumber() < 2:
                             self.DeleteDivergence(next_block)
@@ -850,18 +845,15 @@
                     return
                 wire = wires[0][0]
                 wire.Clean()
-                self.Wires.remove(wire)
-                self.Elements.remove(wire)
+                self.RemoveWire(wire)
                 wires = next.GetWires()
                 if len(wires) != 1:
                     return
                 wire = wires[0][0]
                 wire.Clean()
-                self.Wires.remove(wire)
-                self.Elements.remove(wire)
+                self.RemoveWire(wire)
                 transition.Clean()
-                self.Blocks.remove(transition)
-                self.Elements.remove(transition)
+                self.AddBlock(transition)
                 self.Controler.RemoveCurrentElementEditingInstance(transition.GetId())
                 previous_block.RemoveBranch(previous)
                 if previous_block.GetBranchNumber() < 2:
@@ -890,8 +882,7 @@
                     next_block = next.GetParentBlock()
                     wire = wires[0][0]
                     wire.Clean()
-                    self.Wires.remove(wire)
-                    self.Elements.remove(wire)
+                    self.RemoveWire(wire)
                 else:
                     next = None
                     next_block = None
@@ -901,8 +892,7 @@
                         wire = wires[0][0]
                         previous = wires[0][0].EndConnected
                         wire.Clean()
-                        self.Wires.remove(wire)
-                        self.Elements.remove(wire)
+                        self.RemoveWire(wire)
                     else:
                         if type == SELECTION_CONVERGENCE:
                             wires = connector.GetWires()
@@ -913,8 +903,7 @@
                         previous_connector = wire.EndConnected
                         previous_block = previous_connector.GetParentBlock()
                         wire.Clean()
-                        self.Wires.remove(wire)
-                        self.Elements.remove(wire)
+                        self.RemoveWire(wire)
                         if isinstance(previous_block, SFC_Step):
                             previous_block.RemoveOutput()
                             self.RefreshStepModel(previous_block)
@@ -928,8 +917,7 @@
                             else:
                                 self.DeleteDivergence(previous_block)
                 divergence.Clean()
-                self.Blocks.remove(divergence)
-                self.Elements.remove(divergence)
+                self.AddBlocks(divergence)
                 self.Controler.RemoveCurrentElementEditingInstance(divergence.GetId())
                 if next:
                     wire = self.ConnectConnectors(next, previous)
@@ -951,8 +939,7 @@
                 previous = wire.EndConnected
                 previous_block = previous.GetParentBlock()
                 wire.Clean()
-                self.Wires.remove(wire)
-                self.Elements.remove(wire)
+                self.RemoveWire(wire)
                 wires = connectors["outputs"][0].GetWires()
                 if len(wires) != 1:
                     return
@@ -960,11 +947,9 @@
                 next = wire.StartConnected
                 next_block = next.GetParentBlock()
                 wire.Clean()
-                self.Wires.remove(wire)
-                self.Elements.remove(wire)
+                self.RemoveWire(wire)
                 divergence.Clean()
-                self.Blocks.remove(divergence)
-                self.Elements.remove(divergence)
+                self.AddBlock(divergence)
                 self.Controler.RemoveCurrentElementEditingInstance(divergence.GetId())
                 wire = self.ConnectConnectors(next, previous)
                 previous_pos = previous.GetPosition(False)
@@ -996,11 +981,9 @@
                 return
             wire = wires[0][0]
             wire.Clean()
-            self.Wires.remove(wire)
-            self.Elements.remove(wire)
+            self.RemoveWire(wire)
             jump.Clean()
-            self.Blocks.remove(jump)
-            self.Elements.remove(jump)
+            self.AddBlocks(jump)
             self.Controler.RemoveCurrentElementEditingInstance(jump.GetId())
             if isinstance(previous_block, SFC_Step):
                 previous_block.RemoveOutput()
@@ -1027,11 +1010,9 @@
             wire = wires[0][0]
             step = wire.EndConnected.GetParentBlock()
             wire.Clean()
-            self.Wires.remove(wire)
-            self.Elements.remove(wire)
+            self.RemoveWire(wire)
             actionblock.Clean()
-            self.Blocks.remove(actionblock)
-            self.Elements.remove(actionblock)
+            self.AddBlock(actionblock)
             self.Controler.RemoveCurrentElementEditingInstance(actionblock.GetId())
             step.RemoveAction()
             self.RefreshStepModel(step)
--- a/Viewer.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/Viewer.py	Wed Jul 18 11:51:30 2007 +0200
@@ -120,6 +120,9 @@
         self.DrawGrid = True
         self.current_id = 0    
         
+        # Initialize Block, Wire and Comment numbers
+        self.block_id = self.wire_id = self.comment_id = 0
+        
         # Initialize Viewer mode to Selection mode
         self.Mode = MODE_SELECTION
         self.SavedMode = False
@@ -153,14 +156,60 @@
         return dc
 
 #-------------------------------------------------------------------------------
+#                         Element management functions
+#-------------------------------------------------------------------------------
+
+    def AddBlock(self, block):
+        self.block_id += 1
+        self.Blocks[block] = self.block_id
+        
+    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
+
+    def IsBlock(self, block):
+        return self.Blocks.get(block, False)
+        
+    def IsWire(self, wire):
+        return self.Wires.get(wire, False)
+        
+    def IsComment(self, comment):
+        return self.Comments.get(comment, False)
+
+    def RemoveBlock(self, block):
+        self.Blocks.pop(block)
+        
+    def RemoveWire(self, wire):
+        self.Wires.pop(wire)
+        
+    def RemoveComment(self, comment):
+        self.Comments.pop(comment)
+
+    def GetElements(self, sort_blocks=False, sort_wires=False, sort_comments=False):
+        blocks = self.Blocks.keys()
+        wires = self.Wires.keys()
+        comments = self.Comments.keys()
+        if sort_blocks:
+            blocks.sort(lambda x,y:self.Blocks[x].__cmp__(self.Blocks[y]))
+        if sort_wires:
+            wires.sort(lambda x,y:self.Wires[x].__cmp__(self.Wires[y]))
+        if sort_comments:
+            comments.sort(lambda x,y:self.Comments[x].__cmp__(self.Comments[y]))
+        return blocks + wires + comments
+
+#-------------------------------------------------------------------------------
 #                              Reset functions
 #-------------------------------------------------------------------------------
 
     # Resets Viewer lists
     def ResetView(self):
-        self.Blocks = []
-        self.Wires = []
-        self.Elements = []
+        self.Blocks = {}
+        self.Wires = {}
+        self.Comments = {}
         self.SelectedElement = None
     
     # Changes Viewer mode
@@ -197,14 +246,14 @@
             instance = self.Controler.GetCurrentElementEditingInstanceInfos(exclude=ids)
             if instance:
                 self.loadInstance(instance, ids)
-        self.RefreshScrollBar()
+        self.RefreshScrollBars()
         self.Refresh()
     
-    def RefreshScrollBar(self):
+    def RefreshScrollBars(self):
         xstart, ystart = self.GetViewStart()
         window_size = self.GetClientSize()
         maxx = maxy = 0
-        for element in self.Elements:
+        for element in self.GetElements():
             posx, posy = element.GetPosition()
             width, height = element.GetSize()
             maxx = max(maxx, posx + width)
@@ -226,8 +275,7 @@
             variable = FBD_Variable(self, INPUT, instance["name"], instance["value_type"], instance["id"])
             variable.SetPosition(instance["x"], instance["y"])
             variable.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(variable)
-            self.Elements.append(variable)
+            self.AddBlock(variable)
             connectors = variable.GetConnectors()
             connectors["output"].SetPosition(wxPoint(*instance["connector"]["position"]))
             if instance["connector"]["negated"]:
@@ -238,8 +286,7 @@
             variable = FBD_Variable(self, OUTPUT, instance["name"], instance["value_type"], instance["id"])
             variable.SetPosition(instance["x"], instance["y"])
             variable.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(variable)
-            self.Elements.append(variable)
+            self.AddBlock(variable)
             connectors = variable.GetConnectors()
             connectors["input"].SetPosition(wxPoint(*instance["connector"]["position"]))
             if instance["connector"]["negated"]:
@@ -251,8 +298,7 @@
             variable = FBD_Variable(self, INOUT, instance["name"], instance["value_type"], instance["id"])
             variable.SetPosition(instance["x"], instance["y"])
             variable.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(variable)
-            self.Elements.append(variable)
+            self.AddBlock(variable)
             connectors = variable.GetConnectors()
             connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"]))
             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
@@ -269,16 +315,14 @@
             connection = FBD_Connector(self, CONTINUATION, instance["name"], instance["id"])
             connection.SetPosition(instance["x"], instance["y"])
             connection.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(connection)
-            self.Elements.append(connection)
+            self.AddBlock(connection)
             connector = connection.GetConnector()
             connector.SetPosition(wxPoint(*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.Blocks.append(connection)
-            self.Elements.append(connection)
+            self.AddBlock(connection)
             connector = connection.GetConnector()
             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
             self.CreateWires(connector, instance["connector"]["links"], ids)
@@ -286,20 +330,18 @@
             comment = Comment(self, instance["content"], instance["id"])
             comment.SetPosition(instance["x"], instance["y"])
             comment.SetSize(instance["width"], instance["height"])
-            self.Elements.append(comment)
+            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"])
-            self.Blocks.append(leftpowerrail)
-            self.Elements.append(leftpowerrail)
+            self.AddBlock(leftpowerrail)
             connectors = leftpowerrail.GetConnectors()
             for i, connector in enumerate(instance["connectors"]):
                 connectors[i].SetPosition(wxPoint(*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"])
-            self.Blocks.append(rightpowerrail)
-            self.Elements.append(rightpowerrail)
+            self.AddBlock(rightpowerrail)
             connectors = rightpowerrail.GetConnectors()
             for i, connector in enumerate(instance["connectors"]):
                 connectors[i].SetPosition(wxPoint(*connector["position"]))
@@ -323,8 +365,7 @@
                 contact_type = CONTACT_NORMAL
             contact = LD_Contact(self, contact_type, instance["name"], instance["id"])
             contact.SetPosition(instance["x"], instance["y"])
-            self.Blocks.append(contact)
-            self.Elements.append(contact)
+            self.AddBlock(contact)
             connectors = contact.GetConnectors()
             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
@@ -348,8 +389,7 @@
                 coil_type = COIL_NORMAL
             coil = LD_Coil(self, coil_type, instance["name"], instance["id"])
             coil.SetPosition(instance["x"], instance["y"])
-            self.Blocks.append(coil)
-            self.Elements.append(coil)
+            self.AddBlock(coil)
             connectors = coil.GetConnectors()
             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
@@ -362,8 +402,7 @@
             step = SFC_Step(self, instance["name"], initial, instance["id"])
             step.SetPosition(instance["x"], instance["y"])
             step.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(step)
-            self.Elements.append(step)
+            self.AddBlock(step)
             if "output" in instance["connectors"]:
                 step.AddOutput()
             if "action" in instance["connectors"]:
@@ -379,8 +418,7 @@
         elif instance["type"] == "transition":
             transition = SFC_Transition(self, instance["condition_type"], instance["condition"], instance["id"])
             transition.SetPosition(instance["x"], instance["y"])
-            self.Blocks.append(transition)
-            self.Elements.append(transition)
+            self.AddBlock(transition)
             connectors = transition.GetConnectors()
             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
@@ -400,8 +438,7 @@
                     len(instance["connectors"]["inputs"]), instance["id"])
             divergence.SetPosition(instance["x"], instance["y"])
             divergence.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(divergence)
-            self.Elements.append(divergence)
+            self.AddBlock(divergence)
             connectors = divergence.GetConnectors()
             for i, input_connector in enumerate(instance["connectors"]["inputs"]):
                 connector = connectors["inputs"][i]
@@ -413,8 +450,7 @@
         elif instance["type"] == "jump":
             jump = SFC_Jump(self, instance["target"], instance["id"])
             jump.SetPosition(instance["x"], instance["y"])
-            self.Blocks.append(jump)
-            self.Elements.append(jump)
+            self.AddBlock(jump)
             connector = jump.GetConnector()
             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
             self.CreateWires(connector, instance["connector"]["links"], ids)
@@ -422,8 +458,7 @@
             actionBlock = SFC_ActionBlock(self, instance["actions"], instance["id"])
             actionBlock.SetPosition(instance["x"], instance["y"])
             actionBlock.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(actionBlock)
-            self.Elements.append(actionBlock)
+            self.AddBlock(actionBlock)
             connector = actionBlock.GetConnector()
             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
             self.CreateWires(connector, instance["connector"]["links"], ids)
@@ -434,8 +469,7 @@
                 block = FBD_Block(self, instance["type"], "", instance["id"], len(instance["connectors"]["inputs"]))
             block.SetPosition(instance["x"], instance["y"])
             block.SetSize(instance["width"], instance["height"])
-            self.Blocks.append(block)
-            self.Elements.append(block)
+            self.AddBlock(block)
             connectors = block.GetConnectors()
             for i, input_connector in enumerate(instance["connectors"]["inputs"]):
                 connector = connectors["inputs"][i]
@@ -472,8 +506,7 @@
                         end_connector.Connect((wire, -1), False)
                         wire.ConnectStartPoint(None, start_connector)
                         wire.ConnectEndPoint(None, end_connector)
-                        self.Wires.append(wire)
-                        self.Elements.append(wire)
+                        self.AddWire(wire)
 
 #-------------------------------------------------------------------------------
 #                          Search Element functions
@@ -495,7 +528,7 @@
         if self.SelectedElement and not (exclude_group and isinstance(self.SelectedElement, Graphic_Group)):
             if self.SelectedElement.HitTest(pos) or self.SelectedElement.TestHandle(pos) != (0, 0):
                 return self.SelectedElement
-        for element in self.Elements:
+        for element in self.GetElements():
             if element.HitTest(pos) or element.TestHandle(pos) != (0, 0):
                 return element
         return None
@@ -508,16 +541,18 @@
         return None
     
     def FindElementById(self, id):
-        for element in self.Elements:
+        for element in self.Blocks:
+            if element.GetId() == id:
+                return element
+        for element in self.Comments:
             if element.GetId() == id:
                 return element
         return None
     
     def SearchElements(self, bbox):
         elements = []
-        for element in self.Elements:
-            element_bbox = element.GetBoundingBox()
-            if element_bbox.x >= bbox.x and element_bbox.y >= bbox.y and element_bbox.x + element_bbox.width <= bbox.x + bbox.width and element_bbox.y + element_bbox.height <= bbox.y + bbox.height:
+        for element in self.GetElements():
+            if element.IsInSelection(bbox):
                 elements.append(element)
         return elements
 
@@ -611,42 +646,42 @@
 #-------------------------------------------------------------------------------
 
     def OnNoModifierMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Blocks:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.SetConnectorNegated(False)
         event.Skip()
     
     def OnNegatedMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Blocks:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.SetConnectorNegated(True)
         event.Skip()
 
     def OnRisingEdgeMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Blocks:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.SetConnectorEdge("rising")
         event.Skip()
 
     def OnFallingEdgeMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Blocks:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.SetConnectorEdge("falling")
         event.Skip()
 
     def OnAddSegmentMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Wires:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.AddSegment()
         event.Skip()
 
     def OnDeleteSegmentMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Wires:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.DeleteSegment()
         event.Skip()
 
     def OnAddBranchMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Blocks:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.AddDivergenceBranch(self.SelectedElement)
         event.Skip()
 
     def OnDeleteBranchMenu(self, event):
-        if self.SelectedElement and self.SelectedElement in self.Blocks:
+        if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.RemoveDivergenceBranch(self.SelectedElement)
         event.Skip()
 
@@ -711,8 +746,7 @@
                 wire.Handle = (HANDLE_POINT, 0)
                 wire.ProcessDragging(0, 0)
                 wire.Handle = (HANDLE_POINT, 1)
-                self.Wires.append(wire)
-                self.Elements.append(wire)
+                self.AddWire(wire)
                 if self.SelectedElement:
                     self.SelectedElement.SetSelected(False)
                 self.SelectedElement = wire
@@ -767,10 +801,7 @@
             self.ReleaseMouse()
             self.Refresh()
         elif self.Mode == MODE_WIRE and self.SelectedElement:
-            dc = self.GetLogicalDC()
-            pos = GetScaledEventPosition(event, dc, self.Scaling)
-            connector = self.FindBlockConnector(pos, False)
-            if connector and connector != self.SelectedElement.StartConnected:
+            if self.SelectedElement.EndConnected != None:
                 self.SelectedElement.ResetPoints()
                 self.SelectedElement.OnMotion(event, dc, self.Scaling)
                 self.SelectedElement.GeneratePoints()
@@ -834,7 +865,7 @@
                 move_window.y = 1
             if move_window.x != 0 or move_window.y != 0:
                 self.Scroll(xstart + move_window.x, ystart + move_window.y)
-            self.RefreshScrollBar()
+            self.RefreshScrollBars()
         event.Skip()
 
 #-------------------------------------------------------------------------------
@@ -842,6 +873,9 @@
 #-------------------------------------------------------------------------------
 
     def OnChar(self, event):
+        xpos, ypos = self.GetScrollPos(wxHORIZONTAL), self.GetScrollPos(wxVERTICAL)
+        xmax = self.GetScrollRange(wxHORIZONTAL) - self.GetScrollThumb(wxHORIZONTAL)
+        ymax = self.GetScrollRange(wxVERTICAL) - self.GetScrollThumb(wxVERTICAL)
         keycode = event.GetKeyCode()
         if self.Scaling:
             scaling = self.Scaling
@@ -851,16 +885,35 @@
             self.SelectedElement.Clean()
             self.SelectedElement.Delete()
             self.SelectedElement = None
-        elif keycode == WXK_LEFT and self.SelectedElement:
-            self.SelectedElement.Move(-scaling[0], 0)
-        elif keycode == WXK_RIGHT and self.SelectedElement:
-            self.SelectedElement.Move(scaling[0], 0)
-        elif keycode == WXK_UP and self.SelectedElement:
-            self.SelectedElement.Move(0, -scaling[1])
-        elif keycode == WXK_DOWN and self.SelectedElement:
-            self.SelectedElement.Move(0, scaling[1])
+        elif keycode == WXK_LEFT:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(0, ypos)
+            elif event.ControlDown():
+                self.Scroll(max(0, xpos - 1), ypos)
+            elif self.SelectedElement:
+                self.SelectedElement.Move(-scaling[0], 0)
+        elif keycode == WXK_RIGHT:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(xmax, ypos)
+            elif event.ControlDown():
+                self.Scroll(min(xpos + 1, xmax), ypos)
+            elif self.SelectedElement:
+                self.SelectedElement.Move(scaling[0], 0)
+        elif keycode == WXK_UP:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(xpos, 0)
+            elif event.ControlDown():
+                self.Scroll(xpos, max(0, ypos - 1))
+            elif self.SelectedElement:
+                self.SelectedElement.Move(0, -scaling[1])
+        elif keycode == WXK_DOWN:
+            if event.ControlDown() and event.ShiftDown():
+                self.Scroll(xpos, ymax)
+            elif event.ControlDown():
+                self.Scroll(xpos, min(ypos + 1, ymax))
+            elif self.SelectedElement:
+                self.SelectedElement.Move(0, scaling[1])
         self.Refresh()
-        event.Skip()
 
 #-------------------------------------------------------------------------------
 #                          Model adding functions
@@ -879,10 +932,10 @@
                 block = FBD_Block(self, values["type"], "", id, values["extension"], values["inputs"])
             block.SetPosition(bbox.x, bbox.y)
             block.SetSize(values["width"], values["height"])
-            self.Blocks.append(block)
-            self.Elements.append(block)
+            self.AddBlock(block)
             self.Controler.AddCurrentElementEditingBlock(id)
             self.RefreshBlockModel(block)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
     
@@ -904,10 +957,10 @@
             variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id)
             variable.SetPosition(bbox.x, bbox.y)
             variable.SetSize(values["width"], values["height"])
-            self.Blocks.append(variable)
-            self.Elements.append(variable)
+            self.AddBlock(variable)
             self.Controler.AddCurrentElementEditingVariable(id, values["type"])
             self.RefreshVariableModel(variable)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -920,10 +973,10 @@
             connection = FBD_Connector(self, values["type"], values["name"], id)
             connection.SetPosition(bbox.x, bbox.y)
             connection.SetSize(values["width"], values["height"])
-            self.Blocks.append(connection)
-            self.Elements.append(connection)
+            self.AddBlock(connection)
             self.Controler.AddCurrentElementEditingConnection(id, values["type"])
             self.RefreshConnectionModel(connection)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -936,9 +989,10 @@
             comment.SetPosition(bbox.x, bbox.y)
             min_width, min_height = comment.GetMinSize()
             comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height))
-            self.Elements.append(comment)
+            self.AddComment(comment)
             self.Controler.AddCurrentElementEditingComment(id)
             self.RefreshCommentModel(comment)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -959,10 +1013,10 @@
             contact = LD_Contact(self, values["type"], values["name"], id)
             contact.SetPosition(bbox.x, bbox.y)
             contact.SetSize(values["width"], values["height"])
-            self.Blocks.append(contact)
-            self.Elements.append(contact)
+            self.AddBlock(contact)
             self.Controler.AddCurrentElementEditingContact(id)
             self.RefreshContactModel(contact)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -986,10 +1040,10 @@
             coil = LD_Coil(self, values["type"], values["name"], id)
             coil.SetPosition(bbox.x, bbox.y)
             coil.SetSize(values["width"], values["height"])
-            self.Blocks.append(coil)
-            self.Elements.append(coil)
+            self.AddBlock(coil)
             self.Controler.AddCurrentElementEditingCoil(id)
             self.RefreshCoilModel(contact)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1002,10 +1056,10 @@
             powerrail = LD_PowerRail(self, values["type"], id, [True for i in xrange(values["number"])])
             powerrail.SetPosition(bbox.x, bbox.y)
             powerrail.SetSize(values["width"], values["height"])
-            self.Blocks.append(powerrail)
-            self.Elements.append(powerrail)
+            self.AddBlock(powerrail)
             self.Controler.AddCurrentElementEditingPowerRail(id, values["type"])
             self.RefreshPowerRailModel(powerrail)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1019,10 +1073,10 @@
             transition.SetPosition(bbox.x, bbox.y)
             min_width, min_height = transition.GetMinSize()
             transition.SetSize(max(bbox.width, min_width), max(bbox.height, min_height))
-            self.Blocks.append(transition)
-            self.Elements.append(transition)
+            self.AddBlock(transition)
             self.Controler.AddCurrentElementEditingTransition(id)
             self.RefreshTransitionModel(transition)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1036,10 +1090,10 @@
             divergence.SetPosition(bbox.x, bbox.y)
             min_width, min_height = divergence.GetMinSize()
             divergence.SetSize(max(bbox.width, min_width), max(bbox.height, min_height))
-            self.Blocks.append(divergence)
-            self.Elements.append(divergence)
+            self.AddBlock(divergence)
             self.Controler.AddCurrentElementEditingDivergence(id, values["type"])
             self.RefreshDivergenceModel(divergence)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1062,6 +1116,7 @@
             block.SetSize(values["width"], values["height"])
             block.SetType(values["type"], values["extension"])
             self.RefreshBlockModel(block)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1090,6 +1145,7 @@
                 self.Controler.RemoveCurrentElementEditingInstance(id)
                 self.Controler.AddCurrentElementEditingVariable(id, values["type"])
             self.RefreshVariableModel(variable)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1109,6 +1165,7 @@
                 self.Controler.RemoveCurrentElementEditingInstance(id)
                 self.Controler.AddCurrentElementEditingConnection(id, values["type"])
             self.RefreshConnectionModel(connection)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1130,6 +1187,7 @@
             contact.SetType(values["type"])
             contact.SetSize(values["width"], values["height"])
             self.RefreshContactModel(contact)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1154,6 +1212,7 @@
             coil.SetType(values["type"])
             coil.SetSize(values["width"], values["height"])
             self.RefreshContactModel(coil)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
 
@@ -1170,43 +1229,46 @@
                 self.Controler.RemoveCurrentElementEditingInstance(id)
                 self.Controler.AddCurrentElementEditingPowerRail(id, values["type"])
             self.RefreshPowerRailModel(powerrail)
+            self.RefreshScrollBars()
             self.Refresh()
         dialog.Destroy()
-
-
-    def AddNewTransition(self, bbox):
-        dialog = TransitionContentDialog(self.Parent)
-        dialog.SetTransitions(self.Controler.GetCurrentElementEditingTransitions())
-        if dialog.ShowModal() == wxID_OK:
-            id = self.GetNewId()
-            values = dialog.GetValues()
-            transition = SFC_Transition(self, values["type"], values["value"], id)
-            transition.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = transition.GetMinSize()
-            transition.SetSize(max(bbox.width, min_width), max(bbox.height, min_height))
-            self.Blocks.append(transition)
-            self.Elements.append(transition)
-            self.Controler.AddCurrentElementEditingTransition(id)
-            self.RefreshTransitionModel(transition)
-            self.Refresh()
-        dialog.Destroy()
-
-    def AddNewDivergence(self, bbox):
-        dialog = DivergenceCreateDialog(self.Parent)
-        dialog.SetMinSize((bbox.width, bbox.height))
-        if dialog.ShowModal() == wxID_OK:
-            id = self.GetNewId()
-            values = dialog.GetValues()
-            divergence = SFC_Divergence(self, values["type"], values["number"], id)
-            divergence.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = divergence.GetMinSize()
-            divergence.SetSize(max(bbox.width, min_width), max(bbox.height, min_height))
-            self.Blocks.append(divergence)
-            self.Elements.append(divergence)
-            self.Controler.AddCurrentElementEditingDivergence(id, values["type"])
-            self.RefreshDivergenceModel(divergence)
-            self.Refresh()
-        dialog.Destroy()
+##
+##
+##    def AddNewTransition(self, bbox):
+##        dialog = TransitionContentDialog(self.Parent)
+##        dialog.SetTransitions(self.Controler.GetCurrentElementEditingTransitions())
+##        if dialog.ShowModal() == wxID_OK:
+##            id = self.GetNewId()
+##            values = dialog.GetValues()
+##            transition = SFC_Transition(self, values["type"], values["value"], id)
+##            transition.SetPosition(bbox.x, bbox.y)
+##            min_width, min_height = transition.GetMinSize()
+##            transition.SetSize(max(bbox.width, min_width), max(bbox.height, min_height))
+##            self.Blocks.append(transition)
+##            self.Elements.append(transition)
+##            self.Controler.AddCurrentElementEditingTransition(id)
+##            self.RefreshTransitionModel(transition)
+##            self.RefreshScrollBars()
+##            self.Refresh()
+##        dialog.Destroy()
+##
+##    def AddNewDivergence(self, bbox):
+##        dialog = DivergenceCreateDialog(self.Parent)
+##        dialog.SetMinSize((bbox.width, bbox.height))
+##        if dialog.ShowModal() == wxID_OK:
+##            id = self.GetNewId()
+##            values = dialog.GetValues()
+##            divergence = SFC_Divergence(self, values["type"], values["number"], id)
+##            divergence.SetPosition(bbox.x, bbox.y)
+##            min_width, min_height = divergence.GetMinSize()
+##            divergence.SetSize(max(bbox.width, min_width), max(bbox.height, min_height))
+##            self.Blocks.append(divergence)
+##            self.Elements.append(divergence)
+##            self.Controler.AddCurrentElementEditingDivergence(id, values["type"])
+##            self.RefreshDivergenceModel(divergence)
+##            self.RefreshScrollBars()
+##            self.Refresh()
+##        dialog.Destroy()
 
 #-------------------------------------------------------------------------------
 #                          Model update functions
@@ -1335,8 +1397,7 @@
                 if element not in elements:
                     elements.append(element)
         block.Clean()
-        self.Blocks.remove(block)
-        self.Elements.remove(block)
+        self.RemoveBlock(block)
         self.Controler.RemoveCurrentElementEditingInstance(block.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1348,8 +1409,7 @@
         else:
             elements = []
         variable.Clean()
-        self.Blocks.remove(variable)
-        self.Elements.remove(variable)
+        self.RemoveBlock(variable)
         self.Controler.RemoveCurrentElementEditingInstance(variable.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1360,22 +1420,20 @@
         else:
             elements = []
         connection.Clean()
-        self.Blocks.remove(connection)
-        self.Elements.remove(connection)
+        self.RemoveBlock(connection)
         self.Controler.RemoveCurrentElementEditingInstance(connection.GetId())
         for element in elements:
             element.RefreshModel()
 
     def DeleteComment(self, comment):
-        self.Elements.remove(comment)
+        self.RemoveComment(comment)
         self.Controler.RemoveCurrentElementEditingInstance(comment.GetId())
 
     def DeleteWire(self, wire):
         if wire in self.Wires:
             connected = wire.GetConnected()
             wire.Clean()
-            self.Wires.remove(wire)
-            self.Elements.remove(wire)
+            self.RemoveWire(wire)
             for connector in connected:
                 connector.RefreshParentBlock()
 
@@ -1383,8 +1441,7 @@
         connectors = contact.GetConnectors()
         elements = connectors["output"].GetConnectedBlocks()
         contact.Clean()
-        self.Blocks.remove(contact)
-        self.Elements.remove(contact)
+        self.RemoveBlock(contact)
         self.Controler.RemoveCurrentElementEditingInstance(contact.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1393,8 +1450,7 @@
         connectors = coil.GetConnectors()
         elements = connectors["output"].GetConnectedBlocks()
         coil.Clean()
-        self.Blocks.remove(coil)
-        self.Elements.remove(coil)
+        self.RemoveBlock(coil)
         self.Controler.RemoveCurrentElementEditingInstance(coil.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1407,8 +1463,7 @@
                     if element not in elements:
                         elements.append(element)
         powerrrail.Clean()
-        self.Blocks.remove(powerrrail)
-        self.Elements.remove(powerrrail)
+        self.RemoveBlock(powerrrail)
         self.Controler.RemoveCurrentElementEditingInstance(powerrrail.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1425,8 +1480,7 @@
                 if element not in elements:
                     elements.append(element)
         step.Clean()
-        self.Blocks.remove(step)
-        self.Elements.remove(step)
+        self.RemoveBlock(step)
         self.Controler.RemoveCurrentElementEditingInstance(step.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1439,8 +1493,7 @@
                 if element not in elements:
                     elements.append(element)
         transition.Clean()
-        self.Blocks.remove(transition)
-        self.Elements.remove(transition)
+        self.RemoveBlock(transition)
         self.Controler.RemoveCurrentElementEditingInstance(transition.GetId())
         for element in elements:
             element.RefreshModel()
@@ -1453,22 +1506,19 @@
                 if element not in elements:
                     elements.append(element)
         divergence.Clean()
-        self.Blocks.remove(divergence)
-        self.Elements.remove(divergence)
+        self.RemoveBlock(divergence)
         self.Controler.RemoveCurrentElementEditingInstance(divergence.GetId())
         for element in elements:
             element.RefreshModel()
     
     def DeleteJump(self, jump):
         jump.Clean()
-        self.Blocks.remove(jump)
-        self.Elements.remove(jump)
+        self.RemoveBlock(jump)
         self.Controler.RemoveCurrentElementEditingInstance(jump.GetId())
     
     def DeleteActionBlock(self, actionblock):
         actionblock.Clean()
-        self.Blocks.remove(actionblock)
-        self.Elements.remove(actionblock)
+        self.RemoveBlock(actionblock)
         self.Controler.RemoveCurrentElementEditingInstance(actionblock.GetId())
 
 
@@ -1490,7 +1540,7 @@
 #-------------------------------------------------------------------------------
 
     def OnMoveWindow(self, event):
-        self.RefreshScrollBar()
+        self.RefreshScrollBars()
         event.Skip()
 
     def OnPaint(self, event):
@@ -1503,12 +1553,15 @@
                 dc.DrawLine(i * self.Scaling[0], 0, i * self.Scaling[0], height)
             for i in xrange(1, height / self.Scaling[1] + 1):
                 dc.DrawLine(0, i * self.Scaling[1], width, i * self.Scaling[1])
+        for comment in self.Comments:
+            if comment != self.SelectedElement:
+                comment.Draw(dc)
         for wire in self.Wires:
             if wire != self.SelectedElement:
                 wire.Draw(dc)
-        for element in self.Elements:
-            if element not in self.Wires and element != self.SelectedElement:
-                element.Draw(dc)
+        for block in self.Blocks:
+            if block != self.SelectedElement:
+                block.Draw(dc)
         if self.SelectedElement:
             self.SelectedElement.Draw(dc)
         if self.rubberBand.IsShown():
--- a/graphics/FBD_Objects.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/graphics/FBD_Objects.py	Wed Jul 18 11:51:30 2007 +0200
@@ -48,6 +48,7 @@
         self.Id = id
         self.Inputs = []
         self.Outputs = []
+        self.RefreshNameSize()
         self.SetType(type, extension, inputs)
     
     # Destructor
@@ -66,11 +67,15 @@
         for output in self.Outputs:
             output.UnConnect(delete = True)
     
+    # Refresh the size of text for name
+    def RefreshNameSize(self):
+        dc = wxClientDC(self.Parent)
+        self.NameSize = dc.GetTextExtent(self.Name)
+    
     # Refresh the block bounding box
     def RefreshBoundingBox(self):
-        dc = wxClientDC(self.Parent)
         # Calculate the size of the name outside the block
-        text_width, text_height = dc.GetTextExtent(self.Name)
+        text_width, text_height = self.NameSize
         # Calculate the bounding box size
         bbx_x = self.Pos.x - max(min(1, len(self.Inputs)) * CONNECTOR_SIZE, (text_width - self.Size[0]) / 2)
         bbx_width = self.Size[0] + 1 + (min(1, len(self.Inputs)) + min(1, len(self.Outputs))) * CONNECTOR_SIZE
@@ -151,7 +156,10 @@
     # Changes the block type
     def SetType(self, type, extension, inputs = None):
         if type != self.Type or self.Extension != extension: 
-            self.Type = type
+            if type != self.Type:
+                self.Type = type
+                dc = wxClientDC(self.Parent)
+                self.TypeSize = dc.GetTextExtent(self.Type)
             self.Extension = extension
             # Find the block definition from type given and create the corresponding
             # inputs and outputs
@@ -185,6 +193,7 @@
                 elif output_modifier != "none":
                     connector.SetEdge(output_modifier)
                 self.Outputs.append(connector)
+            self.RefreshMinSize()
             self.RefreshConnectors()
             self.RefreshBoundingBox()
     
@@ -195,6 +204,7 @@
     # Changes the block name
     def SetName(self, name):
         self.Name = name
+        self.RefreshNameSize()
     
     # Returs the block name
     def GetName(self):
@@ -208,23 +218,25 @@
     def GetExtension(self):
         return self.Extension
     
-    # Returns the block minimum size
-    def GetMinSize(self):
-        dc = wxClientDC(self.Parent)
-        text_width, text_height = dc.GetTextExtent(self.Type)
+    # Refresh the block minimum size
+    def RefreshMinSize(self):
         # Calculate the inputs maximum width
         max_input = 0
         for input in self.Inputs:
-            w, h = dc.GetTextExtent(input.GetName())
+            w, h = input.GetNameSize()
             max_input = max(max_input, w)
         # Calculate the outputs maximum width
         max_output = 0
         for output in self.Outputs:
-            w, h = dc.GetTextExtent(output.GetName())
+            w, h = output.GetNameSize()
             max_output = max(max_output, w)
-        width = max(text_width + 10, max_input + max_output + 15)
+        width = max(self.TypeSize[0] + 10, max_input + max_output + 15)
         height = (max(len(self.Inputs), len(self.Outputs)) + 1) * BLOCK_LINE_SIZE
-        return width, height
+        self.MinSize = width, height
+    
+    # Returns the block minimum size
+    def GetMinSize(self):
+        return self.MinSize
     
     # Changes the negated property of the connector handled
     def SetConnectorNegated(self, negated):
@@ -271,11 +283,9 @@
         # Draw a rectangle with the block size
         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
         # Draw block name and block type
-        namewidth, nameheight = dc.GetTextExtent(self.Name)
-        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - namewidth) / 2,
-                self.Pos.y - (nameheight + 2))
-        typewidth, typeheight = dc.GetTextExtent(self.Type)
-        dc.DrawText(self.Type, self.Pos.x + (self.Size[0] - typewidth) / 2,
+        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - self.NameSize[0]) / 2,
+                self.Pos.y - (self.NameSize[1] + 2))
+        dc.DrawText(self.Type, self.Pos.x + (self.Size[0] - self.TypeSize[0]) / 2,
                 self.Pos.y + 5)
         # Draw inputs and outputs connectors
         for input in self.Inputs:
@@ -304,6 +314,7 @@
         self.Id = id
         self.Input = None
         self.Output = None
+        self.RefreshNameSize()
         self.SetType(type, value_type)
     
     # Destructor
@@ -322,9 +333,13 @@
     def Delete(self):
         self.Parent.DeleteVariable(self)
     
+    # Refresh the size of text for name
+    def RefreshNameSize(self):
+        dc = wxClientDC(self.Parent)
+        self.NameSize = dc.GetTextExtent(self.Name)
+    
     # Refresh the variable bounding box
     def RefreshBoundingBox(self):
-        dc = wxClientDC(self.Parent)
         if self.Type in (OUTPUT, INOUT):
             bbx_x = self.Pos.x - CONNECTOR_SIZE
         else:
@@ -417,6 +432,7 @@
     # Changes the variable name
     def SetName(self, name):
         self.Name = name
+        self.RefreshNameSize()
     
     # Returns the variable name
     def GetName(self):
@@ -424,9 +440,7 @@
     
     # Returns the variable minimum size
     def GetMinSize(self):
-        dc = wxClientDC(self.Parent)
-        text_width, text_height = dc.GetTextExtent(self.Name)
-        return text_width + 10, text_height + 10
+        return self.NameSize[0] + 10, self.NameSize[1] + 10
     
     # Method called when a LeftDClick event have been generated
     def OnLeftDClick(self, event, dc, scaling):
@@ -460,9 +474,8 @@
         # Draw a rectangle with the variable size
         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
         # Draw variable name
-        namewidth, nameheight = dc.GetTextExtent(self.Name)
-        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - namewidth) / 2,
-                self.Pos.y + (self.Size[1] - nameheight) / 2)
+        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - self.NameSize[0]) / 2,
+                self.Pos.y + (self.Size[1] - self.NameSize[1]) / 2)
         # Draw connectors
         if self.Input:
             self.Input.Draw(dc)
@@ -495,6 +508,7 @@
         else:
             self.Connector = Connector(self, "", "ANY", wxPoint(0, 0), EAST)
         self.RefreshConnectors()
+        self.RefreshNameSize()
     
     # Destructor
     def __del__(self):
@@ -509,9 +523,13 @@
     def Delete(self):
         self.Parent.DeleteConnection(self)
     
+    # Refresh the size of text for name
+    def RefreshNameSize(self):
+        dc = wxClientDC(self.Parent)
+        self.NameSize = dc.GetTextExtent(self.Name)
+    
     # Refresh the connection bounding box
     def RefreshBoundingBox(self):
-        dc = wxClientDC(self.Parent)
         if self.Type == CONNECTOR:
             bbx_x = self.Pos.x - CONNECTOR_SIZE
         else:
@@ -561,6 +579,7 @@
     # Changes the connection name
     def SetName(self, name):
         self.Name = name
+        self.RefreshNameSize()
         
     # Returns the connection name
     def GetName(self):
@@ -568,8 +587,7 @@
     
     # Returns the connection minimum size
     def GetMinSize(self):
-        dc = wxClientDC(self.Parent)
-        text_width, text_height = dc.GetTextExtent(self.Name)
+        text_width, text_height = self.NameSize
         if text_height % 2 == 1:
             text_height += 1
         return text_width + text_height + 20, text_height + 10
@@ -599,8 +617,7 @@
         dc.SetBrush(wxWHITE_BRUSH)
         # Draw a rectangle with the connection size with arrows in 
         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
-        namewidth, nameheight = dc.GetTextExtent(self.Name)
-        arrowsize = min(self.Size[1] / 2, (self.Size[0] - namewidth - 10) / 2)
+        arrowsize = min(self.Size[1] / 2, (self.Size[0] - self.NameSize[0] - 10) / 2)
         dc.DrawLine(self.Pos.x, self.Pos.y, self.Pos.x + arrowsize, 
                 self.Pos.y + self.Size[1] / 2)
         dc.DrawLine(self.Pos.x + arrowsize, self.Pos.y + self.Size[1] / 2, 
@@ -610,8 +627,8 @@
         dc.DrawLine(self.Pos.x + self.Size[0], self.Pos.y + self.Size[1] / 2, 
                 self.Pos.x + self.Size[0] - arrowsize, self.Pos.y + self.Size[1])
         # Draw variable name
-        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - namewidth) / 2,
-                self.Pos.y + (self.Size[1] - nameheight) / 2)
+        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - self.NameSize[0]) / 2,
+                self.Pos.y + (self.Size[1] - self.NameSize[1]) / 2)
         # Draw connector
         if self.Connector:
             self.Connector.Draw(dc)
--- a/graphics/GraphicCommons.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/graphics/GraphicCommons.py	Wed Jul 18 11:51:30 2007 +0200
@@ -321,6 +321,10 @@
         rect = self.BoundingBox
         return rect.InsideXY(pt.x, pt.y)
     
+    # Returns if the point given is in the bounding box
+    def IsInSelection(self, rect):
+        return rect.InsideXY(self.BoundingBox.x, self.BoundingBox.y) and rect.InsideXY(self.BoundingBox.x + self.BoundingBox.width, self.BoundingBox.y + self.BoundingBox.height)
+    
     # Override this method for refreshing the bounding box
     def RefreshBoundingBox(self):
         pass
@@ -515,12 +519,23 @@
     def __init__(self, parent):
         Graphic_Element.__init__(self, parent)
         self.Elements = []
+        self.RefreshWireExclusion()
         self.RefreshBoundingBox()
     
     # Destructor
     def __del__(self):
         self.Elements = []
     
+    # Refresh the list of wire excluded
+    def RefreshWireExclusion(self):
+        self.WireExcluded = []
+        for element in self.Elements:
+            if isinstance(element, Wire):
+                startblock = element.StartConnected.GetParentBlock()
+                endblock = element.EndConnected.GetParentBlock()
+                if startblock in self.Elements and endblock in self.Elements:
+                    self.WireExcluded.append(element)
+    
     # Make a clone of this group
     def Clone(self):
         clone = Graphic_Group(self.Parent)
@@ -542,6 +557,7 @@
         # Delete all the elements of the group
         for element in self.Elements:
             element.Delete()
+        self.WireExcluded = []
     
     # Returns if the point given is in the bounding box of one of the elements of this group
     def HitTest(self, pt):
@@ -557,6 +573,7 @@
     # Change the elements of the group
     def SetElements(self, elements):
         self.Elements = elements
+        self.RefreshWireExclusion()
         self.RefreshBoundingBox()
     
     # Returns the elements of the group
@@ -569,20 +586,17 @@
             self.Elements.remove(element)
         else:
             self.Elements.append(element)
+        self.RefreshWireExclusion()
         self.RefreshBoundingBox()
     
     # Move this group of elements
     def Move(self, movex, movey):
-        exclude = []
-        for element in self.Elements:
-            if isinstance(element, Wire):
-                exclude.append(element)
         # Move all the elements of the group
         for element in self.Elements:
-            if isinstance(element, Wire):
+            if not isinstance(element, Wire):
+                element.Move(movex, movey, self.WireExcluded)
+            elif element in self.WireExcluded:
                 element.Move(movex, movey, True)
-            else:
-                element.Move(movex, movey, exclude)
         self.RefreshBoundingBox()
     
     # Refreshes the bounding box of this group of elements
@@ -651,6 +665,7 @@
         self.Edge = edge
         self.OneConnected = onlyone
         self.Pen = wxBLACK_PEN
+        self.RefreshNameSize()
     
     # Change the connector pen
     def SetPen(self, pen):
@@ -658,7 +673,7 @@
     
     # Make a clone of the connector
     def Clone(self):
-        return Connector(self.Parent, self.Name, self.Type, wxPoint(self.Pos[0], self.Pos[1]),
+        return Connector(self.ParentBlock, self.Name, self.Type, wxPoint(self.Pos[0], self.Pos[1]),
                 self.Direction, self.Negated)
     
     # Returns the connector parent block
@@ -680,6 +695,19 @@
     # Changes the connector name
     def SetName(self, name):
         self.Name = name
+        self.RefreshNameSize()
+    
+    # Changes the connector name size
+    def RefreshNameSize(self):
+        if self.Name != "":
+            dc = wxClientDC(self.ParentBlock.Parent)
+            self.NameSize = dc.GetTextExtent(self.Name)
+        else:
+            self.NameSize = 0, 0
+    
+    # Returns the connector name size
+    def GetNameSize(self):
+        return self.NameSize
     
     # Returns the wires connected to the connector
     def GetWires(self):
@@ -856,20 +884,18 @@
             xend = xstart + CONNECTOR_SIZE * self.Direction[0]
             yend = ystart + CONNECTOR_SIZE * self.Direction[1]
             dc.DrawLine(xstart + self.Direction[0], ystart + self.Direction[1], xend, yend)
-        # Calculate the position of the text
-        text_size = dc.GetTextExtent(self.Name)
         if self.Direction[0] != 0:
-            ytext = parent_pos[1] + self.Pos.y - text_size[1] / 2
+            ytext = parent_pos[1] + self.Pos.y - self.NameSize[1] / 2
             if self.Direction[0] < 0:
                 xtext = parent_pos[0] + self.Pos.x + 5
             else:
-                xtext = parent_pos[0] + self.Pos.x - (text_size[0] + 5)
+                xtext = parent_pos[0] + self.Pos.x - (self.NameSize[0] + 5)
         if self.Direction[1] != 0:
-            xtext = parent_pos[0] + self.Pos.x - text_size[0] / 2
+            xtext = parent_pos[0] + self.Pos.x - self.NameSize[0] / 2
             if self.Direction[1] < 0:
                 ytext = parent_pos[1] + self.Pos.y + 5
             else:
-                ytext = parent_pos[1] + self.Pos.y - (text_size[1] + 5)
+                ytext = parent_pos[1] + self.Pos.y - (self.NameSize[1] + 5)
         # Draw the text
         dc.DrawText(self.Name, xtext, ytext)
 
@@ -1139,7 +1165,7 @@
         if index == 0 and self.StartConnected:
             return self.StartConnected.GetBlockId(), self.StartConnected.GetName()
         elif index == -1 and self.EndConnected:
-            return self.EndConnected.GetBlockId(), self.StartConnected.GetName()
+            return self.EndConnected.GetBlockId(), self.EndConnected.GetName()
         return None
     
     # Update the wire points position by keeping at most possible the current positions
--- a/graphics/LD_Objects.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/graphics/LD_Objects.py	Wed Jul 18 11:51:30 2007 +0200
@@ -59,16 +59,22 @@
     
     # Forbids to change the power rail size
     def SetSize(self, width, height):
-        if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
+        if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
             Graphic_Element.SetSize(self, width, height)
             self.RefreshConnectors()
     
     # Forbids to select a power rail
     def HitTest(self, pt):
-        if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
+        if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
             return Graphic_Element.HitTest(self, pt) or self.TestConnector(pt, False) != None
         return False
     
+    # Forbids to select a power rail
+    def IsInSelection(self, rect):
+        if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
+            return Graphic_Element.IsInSelection(rect)
+        return False
+    
     # Deletes this power rail by calling the appropriate method
     def Delete(self):
         self.Parent.DeletePowerRail(self)
@@ -301,6 +307,8 @@
         # Create an input and output connector
         self.Input = Connector(self, "", "BOOL", wxPoint(0, self.Size[1] / 2 + 1), WEST)
         self.Output = Connector(self, "", "BOOL", wxPoint(self.Size[0], self.Size[1] / 2 + 1), EAST)
+        self.RefreshNameSize()
+        self.RefreshTypeSize()
     
     # Destructor
     def __del__(self):
@@ -309,7 +317,7 @@
     
     # Forbids to change the contact size
     def SetSize(self, width, height):
-        if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
+        if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
             Graphic_Element.SetSize(self, width, height)
             self.RefreshConnectors()
     
@@ -322,6 +330,29 @@
         self.Input.UnConnect()
         self.Output.UnConnect()
     
+    # Refresh the size of text for name
+    def RefreshNameSize(self):
+        dc = wxClientDC(self.Parent)
+        if self.Name != "":
+            self.NameSize = dc.GetTextExtent(self.Name)
+        else:
+            self.NameSize = 0, 0
+    
+    # Refresh the size of text for type
+    def RefreshTypeSize(self):
+        dc = wxClientDC(self.Parent)
+        typetext = ""
+        if self.Type == CONTACT_REVERSE:
+            typetext = "/"
+        elif self.Type == CONTACT_RISING:
+            typetext = "P"
+        elif self.Type == CONTACT_FALLING:
+            typetext = "N"
+        if typetext != "":
+            self.TypeSize = dc.GetTextExtent(typetext)
+        else:
+            self.TypeSize = 0, 0
+    
     # Refresh the contact bounding box
     def RefreshBoundingBox(self):
         dc = wxClientDC(self.Parent)
@@ -391,6 +422,7 @@
     # Changes the contact name
     def SetName(self, name):
         self.Name = name
+        self.RefreshNameSize()
 
     # Returns the contact name
     def GetName(self):
@@ -424,9 +456,8 @@
         dc.DrawRectangle(self.Pos.x, self.Pos.y, 2, self.Size[1] + 1)
         dc.DrawRectangle(self.Pos.x + self.Size[0] - 1, self.Pos.y, 2, self.Size[1] + 1)
         # Draw contact name
-        namewidth, nameheight = dc.GetTextExtent(self.Name)
-        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - namewidth) / 2,
-                self.Pos.y - (nameheight + 2))
+        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - self.NameSize[0]) / 2,
+                self.Pos.y - (self.NameSize[1] + 2))
         # Draw the modifier symbol in the middle of contact
         typetext = ""
         if self.Type == CONTACT_REVERSE:
@@ -436,9 +467,8 @@
         elif self.Type == CONTACT_FALLING:
             typetext = "N"
         if typetext != "":
-            typewidth, typeheight = dc.GetTextExtent(typetext)
-            dc.DrawText(typetext, self.Pos.x + (self.Size[0] - typewidth) / 2 + 1,
-                    self.Pos.y + (self.Size[1] - typeheight) / 2)
+            dc.DrawText(typetext, self.Pos.x + (self.Size[0] - self.TypeSize[0]) / 2 + 1,
+                    self.Pos.y + (self.Size[1] - self.TypeSize[1]) / 2)
         # Draw input and output connectors
         self.Input.Draw(dc)
         self.Output.Draw(dc)
@@ -465,6 +495,8 @@
         # Create an input and output connector
         self.Input = Connector(self, "", "BOOL", wxPoint(0, self.Size[1] / 2 + 1), WEST)
         self.Output = Connector(self, "", "BOOL", wxPoint(self.Size[0], self.Size[1] / 2 + 1), EAST)
+        self.RefreshNameSize()
+        self.RefreshTypeSize()
         
     # Destructor
     def __del__(self):
@@ -473,7 +505,7 @@
     
     # Forbids to change the contact size
     def SetSize(self, width, height):
-        if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
+        if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
             Graphic_Element.SetSize(self, width, height)
             self.RefreshConnectors()
     
@@ -486,6 +518,29 @@
         self.Input.UnConnect()
         self.Output.UnConnect()
                 
+    # Refresh the size of text for name
+    def RefreshNameSize(self):
+        dc = wxClientDC(self.Parent)
+        if self.Name != "":
+            self.NameSize = dc.GetTextExtent(self.Name)
+        else:
+            self.NameSize = 0, 0
+    
+    # Refresh the size of text for type
+    def RefreshTypeSize(self):
+        dc = wxClientDC(self.Parent)
+        typetext = ""
+        if self.Type == COIL_REVERSE:
+            typetext = "/"
+        elif self.Type == COIL_SET:
+            typetext = "S"
+        elif self.Type == COIL_RESET:
+            typetext = "R"
+        if typetext != "":
+            self.TypeSize = dc.GetTextExtent(typetext)
+        else:
+            self.TypeSize = 0, 0
+    
     # Refresh the coil bounding box
     def RefreshBoundingBox(self):
         dc = wxClientDC(self.Parent)
@@ -555,6 +610,7 @@
     # Changes the coil name
     def SetName(self, name):
         self.Name = name
+        self.RefreshNameSize()
 
     # Returns the coil name
     def GetName(self):
@@ -563,6 +619,7 @@
     # Changes the coil type
     def SetType(self, type):
         self.Type = type
+        self.RefreshTypeSize()
     
     # Returns the coil type
     def GetType(self):
@@ -590,9 +647,8 @@
         dc.SetPen(wxBLACK_PEN)
         dc.DrawPoint(self.Pos.x + 1, self.Pos.y + self.Size[1] / 2 + 1)
         # Draw coil name
-        namewidth, nameheight = dc.GetTextExtent(self.Name)
-        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - namewidth) / 2,
-                self.Pos.y - (nameheight + 2))
+        dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - self.NameSize[0]) / 2,
+                self.Pos.y - (self.NameSize[1] + 2))
         # Draw the modifier symbol in the middle of coil
         typetext = ""
         if self.Type == COIL_REVERSE:
@@ -602,9 +658,8 @@
         elif self.Type == COIL_RESET:
             typetext = "R"
         if typetext != "":
-            typewidth, typeheight = dc.GetTextExtent(typetext)
-            dc.DrawText(typetext, self.Pos.x + (self.Size[0] - typewidth) / 2 + 1,
-                    self.Pos.y + (self.Size[1] - typeheight) / 2)
+            dc.DrawText(typetext, self.Pos.x + (self.Size[0] - self.TypeSize[0]) / 2 + 1,
+                    self.Pos.y + (self.Size[1] - self.TypeSize[1]) / 2)
         # Draw input and output connectors
         self.Input.Draw(dc)
         self.Output.Draw(dc)
--- a/graphics/SFC_Objects.py	Tue Jul 17 12:25:50 2007 +0200
+++ b/graphics/SFC_Objects.py	Wed Jul 18 11:51:30 2007 +0200
@@ -327,7 +327,7 @@
             Graphic_Element.Resize(self, x, y, width, height)
     
     # Method called when a LeftDClick event have been generated
-    def OnLeftDClick(self, event, scaling):
+    def OnLeftDClick(self, event, dc, scaling):
         # Edit the step properties
         self.Parent.EditStepContent(self)