--- 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)