Last bugs on block and wire moving, resizing with cursor fixed
authorlbessard
Wed, 26 Dec 2007 16:38:09 +0100
changeset 138 9c74d00ce93e
parent 137 fc7e0b8ed9d3
child 139 c2d093402005
Last bugs on block and wire moving, resizing with cursor fixed
Adding block alignment on graphical viewers
PLCOpenEditor.py
Viewer.py
graphics/GraphicCommons.py
graphics/LD_Objects.py
graphics/SFC_Objects.py
--- a/PLCOpenEditor.py	Mon Dec 10 15:52:49 2007 +0100
+++ b/PLCOpenEditor.py	Wed Dec 26 16:38:09 2007 +0100
@@ -107,8 +107,7 @@
     "FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", "comment.png", "Create a new comment"),
              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", "variable.png", "Create a new variable"),
              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", "block.png", "Create a new block"),
-             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "connection.png", "Create a new connection"),
-             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARWIRE, "OnWireTool", "wire.png", "Create a new wire")],
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "connection.png", "Create a new connection")],
     "LD"  : [(True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", "comment.png", "Create a new comment"),
              (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", "powerrail.png", "Create a new power rail"),
              (False, DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARRUNG, "OnRungTool", "rung.png", "Create a new rung"),
@@ -117,8 +116,7 @@
              (False, DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARBRANCH, "OnBranchTool", "branch.png", "Create a new branch"),
              (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", "variable.png", "Create a new variable"),
              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", "block.png", "Create a new block"),
-             (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "connection.png", "Create a new connection"),
-             (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARWIRE, "OnWireTool", "wire.png", "Create a new wire")],
+             (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "connection.png", "Create a new connection")],
     "SFC" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", "comment.png", "Create a new comment"),
              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARINITIALSTEP, "OnInitialStepTool", "initial_step.png", "Create a new initial step"),
              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, ID_PLCOPENEDITORTOOLBARSTEP, "OnStepTool", "step.png", "Create a new step"),
@@ -130,8 +128,7 @@
              (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", "block.png", "Create a new block"),
              (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "connection.png", "Create a new connection"),
              (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", "powerrail.png", "Create a new power rail"),
-             (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", "contact.png", "Create a new contact"),
-             (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARWIRE, "OnWireTool", "wire.png", "Create a new wire")],
+             (True, FREEDRAWING_MODE, ID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", "contact.png", "Create a new contact")],
     "ST"  : [],
     "IL"  : []
 }
@@ -856,13 +853,6 @@
             self.GetPage(selected).SetMode(MODE_CONNECTION)
         event.Skip()
 
-    def OnWireTool(self, event):
-        self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARWIRE)
-        selected = self.GetPageSelection()
-        if selected != -1:
-            self.GetPage(selected).SetMode(MODE_WIRE)
-        event.Skip()
-
     def OnPowerRailTool(self, event):
         self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARPOWERRAIL)
         selected = self.GetPageSelection()
--- a/Viewer.py	Mon Dec 10 15:52:49 2007 +0100
+++ b/Viewer.py	Wed Dec 26 16:38:09 2007 +0100
@@ -43,14 +43,21 @@
 #                       Graphic elements Viewer base class
 #-------------------------------------------------------------------------------
 
-# ID Constants for menu items
-[ID_FBDVIEWERCONTEXTUALMENUITEMS0, ID_FBDVIEWERCONTEXTUALMENUITEMS1,
- ID_FBDVIEWERCONTEXTUALMENUITEMS2, ID_FBDVIEWERCONTEXTUALMENUITEMS3,
- ID_FBDVIEWERCONTEXTUALMENUITEMS5, ID_FBDVIEWERCONTEXTUALMENUITEMS6,
- ID_FBDVIEWERCONTEXTUALMENUITEMS8, ID_FBDVIEWERCONTEXTUALMENUITEMS9,
- ID_FBDVIEWERCONTEXTUALMENUITEMS11, ID_FBDVIEWERCONTEXTUALMENUITEMS12,
- ID_FBDVIEWERCONTEXTUALMENUITEMS14, ID_FBDVIEWERCONTEXTUALMENUITEMS15,
-] = [wx.NewId() for _init_coll_ContextualMenu_Items in range(12)]
+# ID Constants for alignment menu items
+[ID_VIEWERALIGNMENTMENUITEMS0, ID_VIEWERALIGNMENTMENUITEMS1,
+ ID_VIEWERALIGNMENTMENUITEMS2, ID_VIEWERALIGNMENTMENUITEMS4,
+ ID_VIEWERALIGNMENTMENUITEMS5, ID_VIEWERALIGNMENTMENUITEMS6,
+] = [wx.NewId() for _init_coll_AlignmentMenu_Items in range(6)]
+
+# ID Constants for contextual menu items
+[ID_VIEWERCONTEXTUALMENUITEMS0, ID_VIEWERCONTEXTUALMENUITEMS1,
+ ID_VIEWERCONTEXTUALMENUITEMS2, ID_VIEWERCONTEXTUALMENUITEMS3,
+ ID_VIEWERCONTEXTUALMENUITEMS5, ID_VIEWERCONTEXTUALMENUITEMS6,
+ ID_VIEWERCONTEXTUALMENUITEMS8, ID_VIEWERCONTEXTUALMENUITEMS9,
+ ID_VIEWERCONTEXTUALMENUITEMS11, ID_VIEWERCONTEXTUALMENUITEMS12,
+ ID_VIEWERCONTEXTUALMENUITEMS14, ID_VIEWERCONTEXTUALMENUITEMS16,
+ ID_VIEWERCONTEXTUALMENUITEMS17,
+] = [wx.NewId() for _init_coll_ContextualMenu_Items in range(13)]
 
 
 class ViewerDropTarget(wx.TextDropTarget):
@@ -155,67 +162,101 @@
             else:
                 event(self, function)
     
+    # Create Alignment Menu items
+    def _init_coll_AlignmentMenu_Items(self, parent):
+        # Create menu items
+        AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS0,
+              kind=wx.ITEM_NORMAL, text=u'Left')
+        AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS1,
+              kind=wx.ITEM_NORMAL, text=u'Center')
+        AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS2,
+              kind=wx.ITEM_NORMAL, text=u'Right')
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS4,
+              kind=wx.ITEM_NORMAL, text=u'Top')
+        AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS5,
+              kind=wx.ITEM_NORMAL, text=u'Middle')
+        AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS6,
+              kind=wx.ITEM_NORMAL, text=u'Bottom')
+        # Link menu event to corresponding called functions
+        self.Bind(wx.EVT_MENU, self.OnAlignLeftMenu,
+              id=ID_VIEWERALIGNMENTMENUITEMS0)
+        self.Bind(wx.EVT_MENU, self.OnAlignCenterMenu,
+              id=ID_VIEWERALIGNMENTMENUITEMS1)
+        self.Bind(wx.EVT_MENU, self.OnAlignRightMenu,
+              id=ID_VIEWERALIGNMENTMENUITEMS2)
+        self.Bind(wx.EVT_MENU, self.OnAlignTopMenu,
+              id=ID_VIEWERALIGNMENTMENUITEMS4)
+        self.Bind(wx.EVT_MENU, self.OnAlignMiddleMenu,
+              id=ID_VIEWERALIGNMENTMENUITEMS5)
+        self.Bind(wx.EVT_MENU, self.OnAlignBottomMenu,
+              id=ID_VIEWERALIGNMENTMENUITEMS6)
+    
     # Create Contextual Menu items
     def _init_coll_ContextualMenu_Items(self, parent):
         # Create menu items
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS0,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS0,
               kind=wx.ITEM_RADIO, text=u'No Modifier')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS1,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS1,
               kind=wx.ITEM_RADIO, text=u'Negated')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS2,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS2,
               kind=wx.ITEM_RADIO, text=u'Rising Edge')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS3,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS3,
               kind=wx.ITEM_RADIO, text=u'Falling Edge')
         parent.AppendSeparator()
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS5,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS5,
               kind=wx.ITEM_NORMAL, text=u'Add Wire Segment')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS6,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS6,
               kind=wx.ITEM_NORMAL, text=u'Delete Wire Segment')
         parent.AppendSeparator()
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS8,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS8,
               kind=wx.ITEM_NORMAL, text=u'Add Divergence Branch')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS9,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS9,
               kind=wx.ITEM_NORMAL, text=u'Delete Divergence Branch')
         parent.AppendSeparator()
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS11,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS11,
               kind=wx.ITEM_NORMAL, text=u'Clear Execution Order')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS12,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS12,
               kind=wx.ITEM_NORMAL, text=u'Reset Execution Order')
         parent.AppendSeparator()
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS14,
+        parent.AppendMenu(ID_VIEWERCONTEXTUALMENUITEMS14, "Alignment", self.AlignmentMenu)
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS16,
               kind=wx.ITEM_NORMAL, text=u'Edit Block')
-        AppendMenu(parent, help='', id=ID_FBDVIEWERCONTEXTUALMENUITEMS15,
+        AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS17,
               kind=wx.ITEM_NORMAL, text=u'Delete')
         # Link menu event to corresponding called functions
         self.Bind(wx.EVT_MENU, self.OnNoModifierMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS0)
+              id=ID_VIEWERCONTEXTUALMENUITEMS0)
         self.Bind(wx.EVT_MENU, self.OnNegatedMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS1)
+              id=ID_VIEWERCONTEXTUALMENUITEMS1)
         self.Bind(wx.EVT_MENU, self.OnRisingEdgeMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS2)
+              id=ID_VIEWERCONTEXTUALMENUITEMS2)
         self.Bind(wx.EVT_MENU, self.OnFallingEdgeMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS3)
+              id=ID_VIEWERCONTEXTUALMENUITEMS3)
         self.Bind(wx.EVT_MENU, self.OnAddSegmentMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS5)
+              id=ID_VIEWERCONTEXTUALMENUITEMS5)
         self.Bind(wx.EVT_MENU, self.OnDeleteSegmentMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS6)
+              id=ID_VIEWERCONTEXTUALMENUITEMS6)
         self.Bind(wx.EVT_MENU, self.OnAddBranchMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS8)
+              id=ID_VIEWERCONTEXTUALMENUITEMS8)
         self.Bind(wx.EVT_MENU, self.OnDeleteBranchMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS9)
+              id=ID_VIEWERCONTEXTUALMENUITEMS9)
         self.Bind(wx.EVT_MENU, self.OnClearExecutionOrderMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS11)
+              id=ID_VIEWERCONTEXTUALMENUITEMS11)
         self.Bind(wx.EVT_MENU, self.OnResetExecutionOrderMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS12)
+              id=ID_VIEWERCONTEXTUALMENUITEMS12)
         self.Bind(wx.EVT_MENU, self.OnEditBlockMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS14)
+              id=ID_VIEWERCONTEXTUALMENUITEMS16)
         self.Bind(wx.EVT_MENU, self.OnDeleteMenu,
-              id=ID_FBDVIEWERCONTEXTUALMENUITEMS15)
+              id=ID_VIEWERCONTEXTUALMENUITEMS17)
     
     # Create and initialize Contextual Menu
     def _init_menus(self):
+        self.AlignmentMenu = wx.Menu(title='')
         self.ContextualMenu = wx.Menu(title='')
         
+        self._init_coll_AlignmentMenu_Items(self.AlignmentMenu)
         self._init_coll_ContextualMenu_Items(self.ContextualMenu)
     
     # Create a new Viewer
@@ -230,6 +271,7 @@
         self.Scaling = None
         #self.Scaling = (8, 8)
         self.DrawGrid = True
+        self.DrawingWire = False
         self.current_id = 0
         self.TagName = tagname
         
@@ -741,75 +783,129 @@
     def PopupBlockMenu(self, connector = None):
         if connector is not None and connector.IsCompatible("BOOL"):
             type = self.Controler.GetEditedElementType(self.TagName)
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS0, True)
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS1, True)
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS2, type != "function")
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS3, type != "function")
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, True)
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, True)
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, type != "function")
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, type != "function")
         else:
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS0, False)
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS1, False)
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS2, False)
-            self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS3, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS5, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS6, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS8, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS9, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS14, self.SelectedElement.GetType() in self.Controler.GetProjectPouNames())
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS15, True)
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
+            self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, self.SelectedElement.GetType() in self.Controler.GetProjectPouNames())
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
         if connector:
             if connector.IsNegated():
-                self.ContextualMenu.Check(ID_FBDVIEWERCONTEXTUALMENUITEMS1, True)
+                self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS1, True)
             elif connector.GetEdge() == "rising":
-                self.ContextualMenu.Check(ID_FBDVIEWERCONTEXTUALMENUITEMS2, True)
+                self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS2, True)
             elif connector.GetEdge() == "falling":
-                self.ContextualMenu.Check(ID_FBDVIEWERCONTEXTUALMENUITEMS3, True)
-            else:
-                self.ContextualMenu.Check(ID_FBDVIEWERCONTEXTUALMENUITEMS0, True)
+                self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS3, True)
+            else:
+                self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS0, True)
         self.PopupMenu(self.ContextualMenu)
     
     def PopupWireMenu(self):
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS0, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS1, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS2, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS3, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS5, True)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS6, True)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS8, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS9, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS14, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS15, True)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, True)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, True)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
         self.PopupMenu(self.ContextualMenu)
     
     def PopupDivergenceMenu(self, connector):
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS0, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS1, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS2, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS3, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS5, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS6, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS8, True)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS9, connector)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS14, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS15, True)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, True)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, connector)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
         self.PopupMenu(self.ContextualMenu)
     
+    def PopupGroupMenu(self):
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, True)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
+        self.PopupMenu(self.ContextualMenu)
+    
     def PopupDefaultMenu(self, block = True):
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS0, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS1, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS2, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS3, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS5, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS6, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS8, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS9, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS14, False)
-        self.ContextualMenu.Enable(ID_FBDVIEWERCONTEXTUALMENUITEMS15, block)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
+        self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, block)
         self.PopupMenu(self.ContextualMenu)
 
 #-------------------------------------------------------------------------------
 #                            Menu items functions
 #-------------------------------------------------------------------------------
 
+    def OnAlignLeftMenu(self, event):
+        if self.SelectedElement and isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.AlignElements(ALIGN_LEFT, None)
+            self.RefreshBuffer()
+        event.Skip()
+    
+    def OnAlignCenterMenu(self, event):
+        if self.SelectedElement and isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.AlignElements(ALIGN_CENTER, None)
+            self.RefreshBuffer()
+        event.Skip()
+    
+    def OnAlignRightMenu(self, event):
+        if self.SelectedElement and isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.AlignElements(ALIGN_RIGHT, None)
+            self.RefreshBuffer()
+        event.Skip()
+    
+    def OnAlignTopMenu(self, event):
+        if self.SelectedElement and isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.AlignElements(None, ALIGN_TOP)
+            self.RefreshBuffer()
+        event.Skip()
+    
+    def OnAlignMiddleMenu(self, event):
+        if self.SelectedElement and isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.AlignElements(None, ALIGN_MIDDLE)
+            self.RefreshBuffer()
+        event.Skip()
+    
+    def OnAlignBottomMenu(self, event):
+        if self.SelectedElement and isinstance(self.SelectedElement, Graphic_Group):
+            self.SelectedElement.AlignElements(None, ALIGN_BOTTOM)
+            self.RefreshBuffer()
+        event.Skip()
+        
     def OnNoModifierMenu(self, event):
         if self.SelectedElement and self.IsBlock(self.SelectedElement):
             self.SelectedElement.SetConnectorNegated(False)
@@ -858,7 +954,7 @@
 
     def OnEditBlockMenu(self, event):
         if self.SelectedElement:
-            self.ParentWindow.EditProjectElement(ITEM_POU, self.SelectedElement.GetType())
+            self.ParentWindow.EditProjectElement(ITEM_POU, "P::%s"%self.SelectedElement.GetType())
         event.Skip()
 
     def OnDeleteMenu(self, event):
@@ -905,42 +1001,55 @@
                     self.SelectedElement.SetSelected(True)
             else:
                 element = self.FindElement(pos)
-                if self.SelectedElement and self.SelectedElement != element:
-                    self.SelectedElement.SetSelected(False)
-                    self.SelectedElement = None
+                connector = self.FindBlockConnector(pos)
+                if self.DrawingWire:
+                    self.DrawingWire = False
+                    if connector:
+                        event.Dragging = lambda : True
+                        self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling)
+                    if self.SelectedElement.EndConnected is not None:
+                        self.SelectedElement.ResetPoints()
+                        self.SelectedElement.GeneratePoints()
+                        self.SelectedElement.RefreshModel()
+                        self.SelectedElement.SetSelected(True)
+                        element = self.SelectedElement
+                        self.RefreshBuffer()
+                    else:
+                        self.SelectedElement.Delete()
+                        element = None
                     self.Refresh(False)
-                if element:
-                    self.SelectedElement = element
-                    self.SelectedElement.OnLeftDown(event, dc, self.Scaling)
-                    self.Refresh(False)
+                elif connector:
+                    self.DrawingWire = True
+                    pos = GetScaledEventPosition(event, self.GetLogicalDC(), self.Scaling)
+                    if (connector.GetDirection() == EAST):
+                        wire = Wire(self, [wx.Point(pos.x, pos.y), EAST], [wx.Point(pos.x, pos.y), WEST])
+                    else:
+                        wire = Wire(self, [wx.Point(pos.x, pos.y), WEST], [wx.Point(pos.x, pos.y), EAST])
+                    wire.oldPos = pos
+                    wire.Handle = (HANDLE_POINT, 0)
+                    wire.ProcessDragging(0, 0)
+                    wire.Handle = (HANDLE_POINT, 1)
+                    self.AddWire(wire)
+                    if self.SelectedElement:
+                        self.SelectedElement.SetSelected(False)
+                    self.SelectedElement = wire
                 else:
-                    self.rubberBand.Reset()
-                    self.rubberBand.OnLeftDown(event, dc, self.Scaling)
+                    if self.SelectedElement and self.SelectedElement != element:
+                        self.SelectedElement.SetSelected(False)
+                        self.SelectedElement = None
+                        self.Refresh(False)
+                    if element:
+                        self.SelectedElement = element
+                        self.SelectedElement.OnLeftDown(event, dc, self.Scaling)
+                        self.Refresh(False)
+                    else:
+                        self.rubberBand.Reset()
+                        self.rubberBand.OnLeftDown(event, dc, self.Scaling)
         elif self.Mode in [MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, 
                            MODE_CONTACT, MODE_COIL, MODE_POWERRAIL, MODE_INITIALSTEP, 
                            MODE_STEP, MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION]:
             self.rubberBand.Reset()
             self.rubberBand.OnLeftDown(event, self.GetLogicalDC(), self.Scaling)
-        elif self.Mode == MODE_WIRE:
-            pos = GetScaledEventPosition(event, self.GetLogicalDC(), self.Scaling)
-            connector = self.FindBlockConnector(pos)
-            if connector:
-                if (connector.GetDirection() == EAST):
-                    wire = Wire(self, [wx.Point(pos.x, pos.y), EAST], [wx.Point(pos.x, pos.y), WEST])
-                else:
-                    wire = Wire(self, [wx.Point(pos.x, pos.y), WEST], [wx.Point(pos.x, pos.y), EAST])
-                wire.oldPos = pos
-                wire.Handle = (HANDLE_POINT, 0)
-                wire.ProcessDragging(0, 0)
-                wire.Handle = (HANDLE_POINT, 1)
-                self.AddWire(wire)
-                if self.SelectedElement:
-                    self.SelectedElement.SetSelected(False)
-                self.SelectedElement = wire
-            elif self.SelectedElement:
-                self.SelectedElement.SetSelected(False)
-                self.SelectedElement = None
-            self.Refresh(False)
         event.Skip()
 
     def OnViewerLeftUp(self, event):
@@ -987,21 +1096,27 @@
                 elif self.Mode == MODE_ACTION:
                     wx.CallAfter(self.AddNewActionBlock, bbox)
         elif self.Mode == MODE_SELECTION and self.SelectedElement:
-            self.SelectedElement.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)
-            wx.CallAfter(self.SetCursor, wx.NullCursor)
-            self.Refresh(False)
-        elif self.Mode == MODE_WIRE and self.SelectedElement:
-            if self.SelectedElement.EndConnected != None:
-                self.SelectedElement.ResetPoints()
-                self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling)
-                self.SelectedElement.GeneratePoints()
-                self.SelectedElement.RefreshModel()
-                self.SelectedElement.SetSelected(True)
-                self.RefreshBuffer()
-            else:
-                self.SelectedElement.Delete()
-                self.SelectedElement = None
-            self.Refresh(False)
+            dc = self.GetLogicalDC()
+            if self.DrawingWire:
+                pos = event.GetLogicalPosition(dc)
+                connector = self.FindBlockConnector(pos)
+                if self.SelectedElement.EndConnected is not None:
+                    self.DrawingWire = False
+                    self.SelectedElement.ResetPoints()
+                    self.SelectedElement.OnMotion(event, dc, self.Scaling)
+                    self.SelectedElement.GeneratePoints()
+                    self.SelectedElement.RefreshModel()
+                    self.SelectedElement.SetSelected(True)
+                    self.RefreshBuffer()
+                elif connector is None:
+                    self.DrawingWire = False
+                    self.SelectedElement.Delete()
+                    self.SelectedElement = None
+                self.Refresh(False)
+            else:
+                self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
+                wx.CallAfter(self.SetCursor, wx.NullCursor)
+                self.Refresh(False)
         if self.Mode != MODE_SELECTION and not self.SavedMode:
             wx.CallAfter(self.ParentWindow.ResetCurrentMode)
         event.Skip()
@@ -1035,16 +1150,16 @@
         if self.rubberBand.IsShown():
             self.rubberBand.OnMotion(event, self.GetLogicalDC(), self.Scaling)
         elif self.Mode == MODE_SELECTION and self.SelectedElement:
-            if self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling):
-                self.Refresh(False)
-        elif self.Mode == MODE_WIRE and self.SelectedElement:
-            dc = self.GetLogicalDC()
-            pos = GetScaledEventPosition(event, dc, self.Scaling)
-            connector = self.FindBlockConnector(pos, False)
-            if not connector or self.SelectedElement.EndConnected == None:
-                self.SelectedElement.ResetPoints()
-                self.SelectedElement.OnMotion(event, dc, self.Scaling)
-                self.SelectedElement.GeneratePoints()
+            if self.DrawingWire:
+                dc = self.GetLogicalDC()
+                pos = GetScaledEventPosition(event, dc, self.Scaling)
+                connector = self.FindBlockConnector(pos, False)
+                if not connector or self.SelectedElement.EndConnected == None:
+                    self.SelectedElement.ResetPoints()
+                    self.SelectedElement.OnMotion(event, dc, self.Scaling)
+                    self.SelectedElement.GeneratePoints()
+                    self.Refresh(False)
+            elif self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling):
                 self.Refresh(False)
         self.UpdateScrollPos(event)
         event.Skip()
@@ -1086,7 +1201,10 @@
             self.SelectedElement = None
             self.RefreshBuffer()
             self.RefreshScrollBars()
-            self.Refresh(False)
+            self.SetCursor(wx.NullCursor)
+            self.Refresh(False)
+        elif keycode == wx.WXK_RETURN and self.SelectedElement:
+            self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
         elif keycode == wx.WXK_LEFT:
             if event.ControlDown() and event.ShiftDown():
                 self.Scroll(0, ypos)
--- a/graphics/GraphicCommons.py	Mon Dec 10 15:52:49 2007 +0100
+++ b/graphics/GraphicCommons.py	Wed Dec 26 16:38:09 2007 +0100
@@ -78,9 +78,12 @@
 [EAST, NORTH, WEST, SOUTH] = [(1,0), (0,-1), (-1,0), (0,1)]
 
 # Contants for defining which mode is selected for each view 
-[MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, MODE_WIRE,
- MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP, MODE_TRANSITION,
- MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(15)
+[MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, 
+ MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP, 
+ MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(14)
+
+# Contants for defining alignment types for graphic group 
+[ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM] = range(6)
 
 # Contants for defining which drawing mode is selected for app
 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2]
@@ -452,10 +455,8 @@
             # If a dragging have been initiated, refreshes the element state
             if self.Dragging:
                 dragx, dragy = self.ProcessDragging(movex, movey)
-                if dragx:
-                    self.oldPos.x = pos.x
-                if dragy:
-                    self.oldPos.y = pos.y
+                self.oldPos.x += dragx
+                self.oldPos.y += dragy
             return True
         # If cursor just pass over the element, changes the cursor if it is on a handle
         else:
@@ -489,34 +490,37 @@
             x = y = start_x = start_y = 0
             width, height = start_width, start_height = self.GetSize()
             if handle[0] == 1:
-                x = movex
+                x = movex = max(-self.BoundingBox.x, movex)
                 width -= movex
             elif handle[0] == 3:
                 width += movex
             if handle[1] == 1:
-                y = movey
+                y = movey = max(-self.BoundingBox.y, movey)
                 height -= movey
             elif handle[1] == 3:
                 height += movey
             # Verify that new size is not lesser than minimum
             min_width, min_height = self.GetMinSize()
-            dragx = dragy = False
             if handle[0] != 2 and (width >= min_width or width > self.Size[0]):
                 start_x = x
                 start_width = width
-                dragx = True
+            else:
+                movex = 0
             if handle[1] != 2 and (height >= min_height or height > self.Size[1]):
                 start_y = y
                 start_height = height
-                dragy = True
-            if dragx or dragy:
+            else:
+                movey = 0
+            if movex != 0 or movey != 0:
                 self.Resize(start_x, start_y, start_width, start_height)
-            return dragx, dragy
+            return movex, movey
         # If it is a move handle, Move this element
         elif handle_type == HANDLE_MOVE:
+            movex = max(-self.BoundingBox.x, movex)
+            movey = max(-self.BoundingBox.y, movey)
             self.Move(movex, movey)
-            return True, True
-        return False, False
+            return movex, movey
+        return 0, 0
     
     # Override this method for defining the method to call for refreshing the model of this element
     def RefreshModel(self, move=True):
@@ -618,6 +622,43 @@
     def GetElements(self):
         return self.Elements
     
+    # Align the group elements
+    def AlignElements(self, horizontally, vertically):
+        minx = self.BoundingBox.x + self.BoundingBox.width
+        miny = self.BoundingBox.y + self.BoundingBox.height
+        maxx = self.BoundingBox.x
+        maxy = self.BoundingBox.y
+        for element in self.Elements:
+            if not isinstance(element, Wire):
+                posx, posy = element.GetPosition()
+                width, height = element.GetSize()
+                minx = min(minx, posx)
+                miny = min(miny, posy)
+                maxx = max(maxx, posx + width)
+                maxy = max(maxy, posy + height)
+        for element in self.Elements:
+            if not isinstance(element, Wire):
+                posx, posy = element.GetPosition()
+                width, height = element.GetSize()
+                movex = movey = 0
+                if horizontally == ALIGN_LEFT:
+                    movex = minx - posx
+                elif horizontally == ALIGN_CENTER:
+                    movex = (maxx + minx - width) / 2 - posx
+                elif horizontally == ALIGN_RIGHT:
+                    movex = maxx - width - posx
+                if vertically == ALIGN_TOP:
+                    movey = miny - posy
+                elif vertically == ALIGN_MIDDLE:
+                    movey = (maxy + miny - height) / 2 - posy
+                elif vertically == ALIGN_BOTTOM:
+                    movey = maxy - height - posy
+                if movex != 0 or movey != 0:
+                    element.Move(movex, movey)
+                    element.RefreshModel()
+        self.RefreshWireExclusion()
+        self.RefreshBoundingBox()
+    
     # Remove or select the given element if it is or not in the group
     def SelectElement(self, element):
         if element in self.Elements:
@@ -675,6 +716,11 @@
         for element in self.Elements:
             element.SetSelected(selected)
 
+    # Method called when a RightUp event has been generated
+    def OnRightUp(self, event, dc, scaling):
+        # Popup the menu with special items for a group
+        self.Parent.PopupGroupMenu()
+
     # Refreshes the model of all the elements of this group
     def RefreshModel(self):
         for element in self.Elements:
@@ -1569,15 +1615,15 @@
                 self.Points[idx + 1].x += movex
                 self.GeneratePoints()
                 if start_x != self.Points[idx].x:
-                    return True, False
+                    return self.Points[idx].x - start_x, 0
             elif self.Segments[idx] in (EAST, WEST):
                 start_y = self.Points[idx].y
                 self.Points[idx].y += movey
                 self.Points[idx + 1].y += movey
                 self.GeneratePoints()
                 if start_y != self.Points[idx].y:
-                    return False, True
-        return False, False
+                    return 0, self.Points[idx].y - start_y
+        return 0, 0
     
     # Adds two points in the middle of the handled segment
     def AddSegment(self):
@@ -1644,10 +1690,42 @@
     
     # Method called when a LeftDClick event has been generated
     def OnLeftDClick(self, event, dc, scaling):
-        self.ResetPoints()
-        self.GeneratePoints()
-        self.RefreshModel()
-        self.Parent.RefreshBuffer()
+        if event.ControlDown():
+            direction = (self.StartPoint[1], self.EndPoint[1])
+            if direction in [(EAST, WEST), (WEST, EAST)]:
+                avgy = (self.StartPoint[0].y + self.EndPoint[0].y) / 2
+                if self.StartConnected is not None:
+                    startblock = self.StartConnected.GetParentBlock()
+                    startblock.Move(0, avgy - self.StartPoint[0].y)
+                    startblock.RefreshModel()
+                else:
+                    self.MoveStartPoint(wx.Point(self.StartPoint[0].x, avgy))
+                if self.EndConnected is not None:
+                    endblock = self.EndConnected.GetParentBlock()
+                    endblock.Move(0, avgy - self.EndPoint[0].y)
+                    endblock.RefreshModel()
+                else:
+                    self.MoveEndPoint(wx.Point(self.EndPoint[0].x, avgy))
+            elif direction in [(NORTH, SOUTH), (SOUTH, NORTH)]:
+                avgx = (self.StartPoint[0].x + self.EndPoint[0].x) / 2
+                if self.StartConnected is not None:
+                    startblock = self.StartConnected.GetParentBlock()
+                    startblock.Move(avgx - self.StartPoint[0].x, 0)
+                    startblock.RefreshModel()
+                else:
+                    self.MoveStartPoint(wx.Point(avgx, self.StartPoint[0].y))
+                if self.EndConnected is not None:
+                    endblock = self.EndConnected.GetParentBlock()
+                    endblock.Move(avgx - self.EndPoint[0].x, 0)
+                    endblock.RefreshModel()
+                else:
+                    self.MoveEndPoint(wx.Point(avgx, self.EndPoint[0].y))
+            self.Parent.RefreshBuffer()
+        else:
+            self.ResetPoints()
+            self.GeneratePoints()
+            self.RefreshModel()
+            self.Parent.RefreshBuffer()
         
     # Method called when a Motion event has been generated
     def OnMotion(self, event, dc, scaling):
@@ -1687,6 +1765,8 @@
         handle_type, handle = self.Handle
         # A point has been handled
         if handle_type == HANDLE_POINT:
+            movex = max(-self.Points[handle].x + POINT_RADIUS, movex)
+            movey = max(-self.Points[handle].y + POINT_RADIUS, movey)
             # Try to connect point to a connector
             new_pos = wx.Point(self.Points[handle].x + movex, self.Points[handle].y + movey)
             connector = self.Parent.FindBlockConnector(new_pos)
@@ -1695,13 +1775,17 @@
                     connector.Connect((self, handle))
                     self.SetStartPointDirection(connector.GetDirection())
                     self.ConnectStartPoint(connector.GetPosition(), connector)
-                    self.oldPos = connector.GetPosition()
+                    pos = connector.GetPosition()
+                    movex = pos.x - self.oldPos.x
+                    movey = pos.y - self.oldPos.y
                     self.Dragging = False
                 elif handle != 0 and self.StartConnected != connector and connector.IsCompatible(self.GetStartConnectedType()):
                     connector.Connect((self, handle))
                     self.SetEndPointDirection(connector.GetDirection())
                     self.ConnectEndPoint(connector.GetPosition(), connector)
-                    self.oldPos = connector.GetPosition()
+                    pos = connector.GetPosition()
+                    movex = pos.x - self.oldPos.x
+                    movey = pos.y - self.oldPos.y
                     self.Dragging = False
                 elif handle == 0:
                     self.MoveStartPoint(new_pos)
@@ -1716,7 +1800,7 @@
                 if self.EndConnected:
                     self.UnConnectEndPoint()
                 self.MoveEndPoint(new_pos)
-            return True, True
+            return movex, movey
         # A segment has been handled, move a segment
         elif handle_type == HANDLE_SEGMENT:
             return self.MoveSegment(handle[0], movex, movey)
--- a/graphics/LD_Objects.py	Mon Dec 10 15:52:49 2007 +0100
+++ b/graphics/LD_Objects.py	Wed Dec 26 16:38:09 2007 +0100
@@ -295,8 +295,9 @@
         handle_type, handle = self.Handle
         # A connector has been handled
         if handle_type == HANDLE_CONNECTOR:
+            movey = max(-self.BoundingBox.y, movey)
             self.MoveConnector(handle, movey)
-            return False, True
+            return 0, movey
         else:
             return Graphic_Element.ProcessDragging(self, movex, movey)
     
--- a/graphics/SFC_Objects.py	Mon Dec 10 15:52:49 2007 +0100
+++ b/graphics/SFC_Objects.py	Wed Dec 26 16:38:09 2007 +0100
@@ -369,21 +369,24 @@
     def ProcessDragging(self, movex, movey):
         handle_type, handle = self.Handle
         if handle_type == HANDLE_MOVE:
+            movex = max(-self.BoundingBox.x, movex)
+            movey = max(-self.BoundingBox.y, movey)
             action_block = None
             if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
                 self.Move(movex, movey)
                 self.RefreshConnected()
-                return True, True
+                return movex, movey
             elif self.Initial:
                 self.MoveActionBlock((movex, movey))
                 self.Move(movex, movey, self.Parent.Wires)
                 self.RefreshOutputPosition((movex, movey))
+                return movex, movey
             else:
                 self.MoveActionBlock((movex, 0))
                 self.Move(movex, 0)
                 self.RefreshInputPosition()
                 self.RefreshOutputPosition()
-            return True, False
+                return movex, 0
         else:
             return Graphic_Element.ProcessDragging(self, movex, movey)
     
@@ -719,10 +722,11 @@
     # Refreshes the transition state according to move defined and handle selected
     def ProcessDragging(self, movex, movey):
         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
+            movex = max(-self.BoundingBox.x, movex)
             self.Move(movex, 0)
             self.RefreshInputPosition()
             self.RefreshOutputPosition()
-            return True, False
+            return movex, 0
         else:
             return Graphic_Element.ProcessDragging(self, movex, movey)
     
@@ -1132,13 +1136,14 @@
         handle_type, handle = self.Handle
         # A connector has been handled
         if handle_type == HANDLE_CONNECTOR:
+            movex = max(-self.BoundingBox.x, movex)
             self.MoveConnector(handle, movex)
             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
                 self.RefreshConnectedPosition(handle)
-            return True, False
+            return movex, 0
         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
             return Graphic_Element.ProcessDragging(self, movex, movey)
-        return False, False
+        return 0, 0
     
     # Refresh output element model
     def RefreshOutputModel(self, move=False):
@@ -1316,9 +1321,10 @@
     # Refreshes the jump state according to move defined and handle selected
     def ProcessDragging(self, movex, movey):
         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
+            movex = max(-self.BoundingBox.x, movex)
             self.Move(movex, 0)
             self.RefreshInputPosition()
-            return True, False
+            return movex, 0
         else:
             return Graphic_Element.ProcessDragging(self, movex, movey)
     
@@ -1505,13 +1511,14 @@
         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
             handle_type, handle = self.Handle
             if handle_type == HANDLE_MOVE:
+                movex = max(-self.BoundingBox.x, movex)
                 wires = self.Input.GetWires()
                 if len(wires) == 1:
                     input_pos = wires[0][0].EndConnected.GetPosition(False)
                     if self.Pos.x - input_pos.x + movex >= SFC_WIRE_MIN_SIZE:
                         self.Move(movex, 0)
-                        return True, False
-                return False, False
+                        return movex, 0
+                return 0, 0
             else:
                 return Graphic_Element.ProcessDragging(self, movex, movey)
         else: