graphics/GraphicCommons.py
changeset 138 9c74d00ce93e
parent 112 317148fc1225
child 140 06d28f03f6f4
--- 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)