graphics/GraphicCommons.py
changeset 331 9106d66bd204
parent 329 1cf72cb51dc9
child 333 0a74fcfd4d03
--- a/graphics/GraphicCommons.py	Wed Mar 18 16:42:12 2009 +0100
+++ b/graphics/GraphicCommons.py	Thu Mar 19 18:10:12 2009 +0100
@@ -115,6 +115,16 @@
     (2, 3) : 5
 }
 
+def round_scaling(x, n, constraint=0):
+    fraction = float(x) / float(n)
+    if constraint == - 1:
+        xround = int(fraction)
+    else:
+        xround = round(fraction)
+        if constraint == 1 and int(fraction) == xround:
+            xround += 1
+    return xround * n
+
 """
 Basic vector operations for calculate wire points
 """
@@ -371,6 +381,10 @@
     def GetSize(self):
         return self.Size.GetWidth(), self.Size.GetHeight()
     
+    # Returns the minimum element size
+    def GetMinSize(self):
+        return 0, 0
+    
     # Refresh the element Bounding Box
     def RefreshBoundingBox(self):
         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
@@ -566,6 +580,20 @@
         self.Move(x, y)
         self.SetSize(width, height)
     
+    # Moves and Resizes the element for fitting scaling
+    def AdjustToScaling(self, scaling):
+        if scaling is not None:
+            movex = round_scaling(self.Pos.x, scaling[0]) - self.Pos.x
+            movey = round_scaling(self.Pos.y, scaling[1]) - self.Pos.y
+            min_width, min_height = self.GetMinSize()
+            width = max(round_scaling(min_width, scaling[0], 1),
+                        round_scaling(self.Size.width, scaling[0]))
+            height = max(round_scaling(min_height, scaling[1], 1),
+                         round_scaling(self.Size.height, scaling[1]))
+            self.Resize(movex, movey, width, height)
+            return movex, movey
+        return 0, 0
+    
     # Refreshes the element state according to move defined and handle selected
     def ProcessDragging(self, movex, movey, event, scaling, width_fac = 1, height_fac = 1):
         handle_type, handle = self.Handle
@@ -579,7 +607,7 @@
             if handle[0] == 1:
                 movex = max(-self.BoundingBox.x, movex)
                 if scaling is not None:
-                    movex = -(round(float(width - movex) / float(scaling[0])) * scaling[0] - width)
+                    movex = -(round_scaling(width - movex, scaling[0]) - width)
                 x = movex
                 if event.ShiftDown():
                     width -= 2 * movex
@@ -587,7 +615,7 @@
                     width -= movex
             elif handle[0] == 3:
                 if scaling is not None:
-                    movex = round(float(width + movex) / float(scaling[0])) * scaling[0] - width
+                    movex = round_scaling(width + movex, scaling[0]) - width
                 if event.ShiftDown():
                     x = -movex
                     width += 2 * movex
@@ -596,7 +624,7 @@
             if handle[1] == 1:
                 movey = max(-self.BoundingBox.y, movey)
                 if scaling is not None:
-                    movey = -(round(float(height - movey) / float(scaling[1])) * scaling[1] - height)
+                    movey = -(round_scaling(height - movey, scaling[1]) - height)
                 y = movey
                 if event.ShiftDown():
                     height -= 2 * movey
@@ -604,7 +632,7 @@
                     height -= movey
             elif handle[1] == 3:
                 if scaling is not None:
-                    movey = round(float(height + movey) / float(scaling[1])) * scaling[1] - height
+                    movey = round_scaling(height + movey, scaling[1]) - height
                 if event.ShiftDown():
                     y = -movey
                     height += 2 * movey
@@ -630,8 +658,8 @@
             movex = max(-self.BoundingBox.x, movex)
             movey = max(-self.BoundingBox.y, movey)
             if scaling is not None:
-                movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
-                movey = round(float(self.Pos.y + movey) / float(scaling[1])) * scaling[1] - self.Pos.y
+                movex = round_scaling(self.Pos.x + movex, scaling[0]) - self.Pos.x
+                movey = round_scaling(self.Pos.y + movey, scaling[1]) - self.Pos.y
             if event.ControlDown():
                 self.CurrentDrag.x = self.CurrentDrag.x + movex
                 self.CurrentDrag.y = self.CurrentDrag.y + movey
@@ -900,6 +928,15 @@
     def GetSize(self):
         return self.BoundingBox.width, self.BoundingBox.height
 
+    # Moves and Resizes the group elements for fitting scaling
+    def AdjustToScaling(self, scaling):
+        movex_max = movey_max = 0
+        for element in self.Elements:
+            movex, movey = element.AdjustToScaling(scaling)
+            movex_max = max(movex_max, abs(movex))
+            movey_max = max(movey_max, abs(movey))
+        return movex_max, movey_max
+    
     # Change the variable that indicates if this element is highlighted
     def SetHighlighted(self, highlighted):
         for element in self.Elements:
@@ -1397,6 +1434,39 @@
     def SetSize(width, height):
         pass
     
+    # Moves and Resizes the element for fitting scaling
+    def AdjustToScaling(self, scaling):
+        if scaling is not None:
+            movex_max = movey_max = 0
+            for idx, point in enumerate(self.Points):
+                if 0 < idx < len(self.Points) - 1:
+                    movex = round_scaling(point.x, scaling[0]) - point.x
+                    movey = round_scaling(point.y, scaling[1]) - point.y
+                    if idx == 1:
+                        if self.Segments[0][0] == 0:
+                            movex = 0
+                        elif (point.x + movex - self.Points[0].x) * self.Segments[0][0] < MIN_SEGMENT_SIZE:
+                            movex = round_scaling(self.Points[0].x + MIN_SEGMENT_SIZE * self.Segments[0][0], scaling[0], self.Segments[0][0]) - point.x
+                        if self.Segments[0][1] == 0:
+                            movey = 0
+                        elif (point.y + movey - self.Points[0].y) * self.Segments[0][1] < MIN_SEGMENT_SIZE:
+                            movey = round_scaling(self.Points[0].y + MIN_SEGMENT_SIZE * self.Segments[0][1], scaling[0], self.Segments[0][1]) - point.y
+                    elif idx == len(self.Points) - 2:
+                        if self.Segments[-1][0] == 0:
+                            movex = 0
+                        elif (self.Points[-1].x - (point.x + movex)) * self.Segments[-1][0] < MIN_SEGMENT_SIZE:
+                            movex = round_scaling(self.Points[-1].x + MIN_SEGMENT_SIZE * self.Segments[0][0], scaling[0], self.Segments[0][0]) - point.x
+                        if self.Segments[-1][1] == 0:
+                            movey = 0
+                        elif (self.Points[-1].y - (point.y + movey)) * self.Segments[-1][1] < MIN_SEGMENT_SIZE:
+                            movey = round_scaling(self.Points[-1].y - MIN_SEGMENT_SIZE * self.Segments[-1][1], scaling[1], -self.Segments[-1][1]) - point.y
+                    movex_max = max(movex_max, movex)
+                    movey_max = max(movey_max, movey)
+                    point.x += movex
+                    point.y += movey
+            return movex_max, movey_max
+        return 0, 0
+    
     # Returns connector to which start point is connected
     def GetStartConnected(self):
         return self.StartConnected
@@ -2029,7 +2099,11 @@
             if self.Segments[idx] in (NORTH, SOUTH):
                 start_x = self.Points[idx].x
                 if scaling is not None:
-                    movex = round(float(self.Points[idx].x + movex) / float(scaling[0])) * scaling[0] - self.Points[idx].x
+                    movex = round_scaling(self.Points[idx].x + movex, scaling[0]) - self.Points[idx].x
+                    if idx == 1 and (self.Points[1].x + movex - self.Points[0].x) * self.Segments[0][0] < MIN_SEGMENT_SIZE:
+                        movex = round_scaling(self.Points[0].x + MIN_SEGMENT_SIZE * self.Segments[0][0], scaling[0], self.Segments[0][0]) - self.Points[idx].x
+                    elif idx == len(self.Segments) - 2 and (self.Points[-1].x - (self.Points[-2].x + movex)) * self.Segments[-1][0] < MIN_SEGMENT_SIZE:
+                        movex = round_scaling(self.Points[-1].x - MIN_SEGMENT_SIZE * self.Segments[-1][0], scaling[0], -self.Segments[-1][0]) - self.Points[idx].x
                 self.Points[idx].x += movex
                 self.Points[idx + 1].x += movex
                 self.GeneratePoints()
@@ -2038,7 +2112,11 @@
             elif self.Segments[idx] in (EAST, WEST):
                 start_y = self.Points[idx].y
                 if scaling is not None:
-                    movey = round(float(self.Points[idx].y + movey) / float(scaling[1])) * scaling[1] - self.Points[idx].y
+                    movey = round_scaling(self.Points[idx].y + movey, scaling[1]) - self.Points[idx].y
+                    if idx == 1 and (self.Points[1].y + movey - self.Points[0].y) * self.Segments[0][1] < MIN_SEGMENT_SIZE:
+                        movex = round_scaling(self.Points[0].y + MIN_SEGMENT_SIZE * self.Segments[0][1], scaling[0], self.Segments[0][1]) - self.Points[idx].y
+                    elif idx == len(self.Segments) - 2 and (self.Points[-1].y - (self.Points[-2].y + movey)) * self.Segments[-1][1] < MIN_SEGMENT_SIZE:
+                        movey = round_scaling(self.Points[idx].y - MIN_SEGMENT_SIZE * self.Segments[-1][1], scaling[1], -self.Segments[-1][1]) - self.Points[idx].y
                 self.Points[idx].y += movey
                 self.Points[idx + 1].y += movey
                 self.GeneratePoints()
@@ -2220,8 +2298,8 @@
             movex = max(-self.Points[handle].x + POINT_RADIUS, movex)
             movey = max(-self.Points[handle].y + POINT_RADIUS, movey)
             if scaling is not None:
-                movex = round(float(self.Points[handle].x + movex) / float(scaling[0])) * scaling[0] - self.Points[handle].x
-                movey = round(float(self.Points[handle].y + movey) / float(scaling[1])) * scaling[1] - self.Points[handle].y
+                movex = round_scaling(self.Points[handle].x + movex, scaling[0]) - self.Points[handle].x
+                movey = round_scaling(self.Points[handle].y + movey, scaling[1]) - self.Points[handle].y
             # 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, self.GetConnectionDirection())