graphics/GraphicCommons.py
changeset 138 9c74d00ce93e
parent 112 317148fc1225
child 140 06d28f03f6f4
equal deleted inserted replaced
137:fc7e0b8ed9d3 138:9c74d00ce93e
    76 
    76 
    77 # Contants for defining the direction of a connector
    77 # Contants for defining the direction of a connector
    78 [EAST, NORTH, WEST, SOUTH] = [(1,0), (0,-1), (-1,0), (0,1)]
    78 [EAST, NORTH, WEST, SOUTH] = [(1,0), (0,-1), (-1,0), (0,1)]
    79 
    79 
    80 # Contants for defining which mode is selected for each view 
    80 # Contants for defining which mode is selected for each view 
    81 [MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, MODE_WIRE,
    81 [MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, 
    82  MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP, MODE_TRANSITION,
    82  MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP, 
    83  MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(15)
    83  MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(14)
       
    84 
       
    85 # Contants for defining alignment types for graphic group 
       
    86 [ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM] = range(6)
    84 
    87 
    85 # Contants for defining which drawing mode is selected for app
    88 # Contants for defining which drawing mode is selected for app
    86 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2]
    89 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2]
    87 
    90 
    88 CURSORS = None
    91 CURSORS = None
   450             if not self.Dragging and (abs(movex) > MIN_MOVE or abs(movey) > MIN_MOVE):
   453             if not self.Dragging and (abs(movex) > MIN_MOVE or abs(movey) > MIN_MOVE):
   451                 self.Dragging = True
   454                 self.Dragging = True
   452             # If a dragging have been initiated, refreshes the element state
   455             # If a dragging have been initiated, refreshes the element state
   453             if self.Dragging:
   456             if self.Dragging:
   454                 dragx, dragy = self.ProcessDragging(movex, movey)
   457                 dragx, dragy = self.ProcessDragging(movex, movey)
   455                 if dragx:
   458                 self.oldPos.x += dragx
   456                     self.oldPos.x = pos.x
   459                 self.oldPos.y += dragy
   457                 if dragy:
       
   458                     self.oldPos.y = pos.y
       
   459             return True
   460             return True
   460         # If cursor just pass over the element, changes the cursor if it is on a handle
   461         # If cursor just pass over the element, changes the cursor if it is on a handle
   461         else:
   462         else:
   462             pos = event.GetLogicalPosition(dc)
   463             pos = event.GetLogicalPosition(dc)
   463             handle = self.TestHandle(pos)
   464             handle = self.TestHandle(pos)
   487         # If it is a resize handle, calculate the values from resizing
   488         # If it is a resize handle, calculate the values from resizing
   488         if handle_type == HANDLE_RESIZE:
   489         if handle_type == HANDLE_RESIZE:
   489             x = y = start_x = start_y = 0
   490             x = y = start_x = start_y = 0
   490             width, height = start_width, start_height = self.GetSize()
   491             width, height = start_width, start_height = self.GetSize()
   491             if handle[0] == 1:
   492             if handle[0] == 1:
   492                 x = movex
   493                 x = movex = max(-self.BoundingBox.x, movex)
   493                 width -= movex
   494                 width -= movex
   494             elif handle[0] == 3:
   495             elif handle[0] == 3:
   495                 width += movex
   496                 width += movex
   496             if handle[1] == 1:
   497             if handle[1] == 1:
   497                 y = movey
   498                 y = movey = max(-self.BoundingBox.y, movey)
   498                 height -= movey
   499                 height -= movey
   499             elif handle[1] == 3:
   500             elif handle[1] == 3:
   500                 height += movey
   501                 height += movey
   501             # Verify that new size is not lesser than minimum
   502             # Verify that new size is not lesser than minimum
   502             min_width, min_height = self.GetMinSize()
   503             min_width, min_height = self.GetMinSize()
   503             dragx = dragy = False
       
   504             if handle[0] != 2 and (width >= min_width or width > self.Size[0]):
   504             if handle[0] != 2 and (width >= min_width or width > self.Size[0]):
   505                 start_x = x
   505                 start_x = x
   506                 start_width = width
   506                 start_width = width
   507                 dragx = True
   507             else:
       
   508                 movex = 0
   508             if handle[1] != 2 and (height >= min_height or height > self.Size[1]):
   509             if handle[1] != 2 and (height >= min_height or height > self.Size[1]):
   509                 start_y = y
   510                 start_y = y
   510                 start_height = height
   511                 start_height = height
   511                 dragy = True
   512             else:
   512             if dragx or dragy:
   513                 movey = 0
       
   514             if movex != 0 or movey != 0:
   513                 self.Resize(start_x, start_y, start_width, start_height)
   515                 self.Resize(start_x, start_y, start_width, start_height)
   514             return dragx, dragy
   516             return movex, movey
   515         # If it is a move handle, Move this element
   517         # If it is a move handle, Move this element
   516         elif handle_type == HANDLE_MOVE:
   518         elif handle_type == HANDLE_MOVE:
       
   519             movex = max(-self.BoundingBox.x, movex)
       
   520             movey = max(-self.BoundingBox.y, movey)
   517             self.Move(movex, movey)
   521             self.Move(movex, movey)
   518             return True, True
   522             return movex, movey
   519         return False, False
   523         return 0, 0
   520     
   524     
   521     # Override this method for defining the method to call for refreshing the model of this element
   525     # Override this method for defining the method to call for refreshing the model of this element
   522     def RefreshModel(self, move=True):
   526     def RefreshModel(self, move=True):
   523         pass
   527         pass
   524     
   528     
   616     
   620     
   617     # Returns the elements of the group
   621     # Returns the elements of the group
   618     def GetElements(self):
   622     def GetElements(self):
   619         return self.Elements
   623         return self.Elements
   620     
   624     
       
   625     # Align the group elements
       
   626     def AlignElements(self, horizontally, vertically):
       
   627         minx = self.BoundingBox.x + self.BoundingBox.width
       
   628         miny = self.BoundingBox.y + self.BoundingBox.height
       
   629         maxx = self.BoundingBox.x
       
   630         maxy = self.BoundingBox.y
       
   631         for element in self.Elements:
       
   632             if not isinstance(element, Wire):
       
   633                 posx, posy = element.GetPosition()
       
   634                 width, height = element.GetSize()
       
   635                 minx = min(minx, posx)
       
   636                 miny = min(miny, posy)
       
   637                 maxx = max(maxx, posx + width)
       
   638                 maxy = max(maxy, posy + height)
       
   639         for element in self.Elements:
       
   640             if not isinstance(element, Wire):
       
   641                 posx, posy = element.GetPosition()
       
   642                 width, height = element.GetSize()
       
   643                 movex = movey = 0
       
   644                 if horizontally == ALIGN_LEFT:
       
   645                     movex = minx - posx
       
   646                 elif horizontally == ALIGN_CENTER:
       
   647                     movex = (maxx + minx - width) / 2 - posx
       
   648                 elif horizontally == ALIGN_RIGHT:
       
   649                     movex = maxx - width - posx
       
   650                 if vertically == ALIGN_TOP:
       
   651                     movey = miny - posy
       
   652                 elif vertically == ALIGN_MIDDLE:
       
   653                     movey = (maxy + miny - height) / 2 - posy
       
   654                 elif vertically == ALIGN_BOTTOM:
       
   655                     movey = maxy - height - posy
       
   656                 if movex != 0 or movey != 0:
       
   657                     element.Move(movex, movey)
       
   658                     element.RefreshModel()
       
   659         self.RefreshWireExclusion()
       
   660         self.RefreshBoundingBox()
       
   661     
   621     # Remove or select the given element if it is or not in the group
   662     # Remove or select the given element if it is or not in the group
   622     def SelectElement(self, element):
   663     def SelectElement(self, element):
   623         if element in self.Elements:
   664         if element in self.Elements:
   624             self.Elements.remove(element)
   665             self.Elements.remove(element)
   625         else:
   666         else:
   672 
   713 
   673     # Change the variable that indicates if the elemente is selected
   714     # Change the variable that indicates if the elemente is selected
   674     def SetSelected(self, selected):
   715     def SetSelected(self, selected):
   675         for element in self.Elements:
   716         for element in self.Elements:
   676             element.SetSelected(selected)
   717             element.SetSelected(selected)
       
   718 
       
   719     # Method called when a RightUp event has been generated
       
   720     def OnRightUp(self, event, dc, scaling):
       
   721         # Popup the menu with special items for a group
       
   722         self.Parent.PopupGroupMenu()
   677 
   723 
   678     # Refreshes the model of all the elements of this group
   724     # Refreshes the model of all the elements of this group
   679     def RefreshModel(self):
   725     def RefreshModel(self):
   680         for element in self.Elements:
   726         for element in self.Elements:
   681             element.RefreshModel()
   727             element.RefreshModel()
  1567                 start_x = self.Points[idx].x
  1613                 start_x = self.Points[idx].x
  1568                 self.Points[idx].x += movex
  1614                 self.Points[idx].x += movex
  1569                 self.Points[idx + 1].x += movex
  1615                 self.Points[idx + 1].x += movex
  1570                 self.GeneratePoints()
  1616                 self.GeneratePoints()
  1571                 if start_x != self.Points[idx].x:
  1617                 if start_x != self.Points[idx].x:
  1572                     return True, False
  1618                     return self.Points[idx].x - start_x, 0
  1573             elif self.Segments[idx] in (EAST, WEST):
  1619             elif self.Segments[idx] in (EAST, WEST):
  1574                 start_y = self.Points[idx].y
  1620                 start_y = self.Points[idx].y
  1575                 self.Points[idx].y += movey
  1621                 self.Points[idx].y += movey
  1576                 self.Points[idx + 1].y += movey
  1622                 self.Points[idx + 1].y += movey
  1577                 self.GeneratePoints()
  1623                 self.GeneratePoints()
  1578                 if start_y != self.Points[idx].y:
  1624                 if start_y != self.Points[idx].y:
  1579                     return False, True
  1625                     return 0, self.Points[idx].y - start_y
  1580         return False, False
  1626         return 0, 0
  1581     
  1627     
  1582     # Adds two points in the middle of the handled segment
  1628     # Adds two points in the middle of the handled segment
  1583     def AddSegment(self):
  1629     def AddSegment(self):
  1584         handle_type, handle = self.Handle
  1630         handle_type, handle = self.Handle
  1585         if handle_type == HANDLE_SEGMENT:
  1631         if handle_type == HANDLE_SEGMENT:
  1642             # Execute the default method for a graphic element
  1688             # Execute the default method for a graphic element
  1643             Graphic_Element.OnRightUp(self, event, dc, scaling)
  1689             Graphic_Element.OnRightUp(self, event, dc, scaling)
  1644     
  1690     
  1645     # Method called when a LeftDClick event has been generated
  1691     # Method called when a LeftDClick event has been generated
  1646     def OnLeftDClick(self, event, dc, scaling):
  1692     def OnLeftDClick(self, event, dc, scaling):
  1647         self.ResetPoints()
  1693         if event.ControlDown():
  1648         self.GeneratePoints()
  1694             direction = (self.StartPoint[1], self.EndPoint[1])
  1649         self.RefreshModel()
  1695             if direction in [(EAST, WEST), (WEST, EAST)]:
  1650         self.Parent.RefreshBuffer()
  1696                 avgy = (self.StartPoint[0].y + self.EndPoint[0].y) / 2
       
  1697                 if self.StartConnected is not None:
       
  1698                     startblock = self.StartConnected.GetParentBlock()
       
  1699                     startblock.Move(0, avgy - self.StartPoint[0].y)
       
  1700                     startblock.RefreshModel()
       
  1701                 else:
       
  1702                     self.MoveStartPoint(wx.Point(self.StartPoint[0].x, avgy))
       
  1703                 if self.EndConnected is not None:
       
  1704                     endblock = self.EndConnected.GetParentBlock()
       
  1705                     endblock.Move(0, avgy - self.EndPoint[0].y)
       
  1706                     endblock.RefreshModel()
       
  1707                 else:
       
  1708                     self.MoveEndPoint(wx.Point(self.EndPoint[0].x, avgy))
       
  1709             elif direction in [(NORTH, SOUTH), (SOUTH, NORTH)]:
       
  1710                 avgx = (self.StartPoint[0].x + self.EndPoint[0].x) / 2
       
  1711                 if self.StartConnected is not None:
       
  1712                     startblock = self.StartConnected.GetParentBlock()
       
  1713                     startblock.Move(avgx - self.StartPoint[0].x, 0)
       
  1714                     startblock.RefreshModel()
       
  1715                 else:
       
  1716                     self.MoveStartPoint(wx.Point(avgx, self.StartPoint[0].y))
       
  1717                 if self.EndConnected is not None:
       
  1718                     endblock = self.EndConnected.GetParentBlock()
       
  1719                     endblock.Move(avgx - self.EndPoint[0].x, 0)
       
  1720                     endblock.RefreshModel()
       
  1721                 else:
       
  1722                     self.MoveEndPoint(wx.Point(avgx, self.EndPoint[0].y))
       
  1723             self.Parent.RefreshBuffer()
       
  1724         else:
       
  1725             self.ResetPoints()
       
  1726             self.GeneratePoints()
       
  1727             self.RefreshModel()
       
  1728             self.Parent.RefreshBuffer()
  1651         
  1729         
  1652     # Method called when a Motion event has been generated
  1730     # Method called when a Motion event has been generated
  1653     def OnMotion(self, event, dc, scaling):
  1731     def OnMotion(self, event, dc, scaling):
  1654         pos = GetScaledEventPosition(event, dc, scaling)
  1732         pos = GetScaledEventPosition(event, dc, scaling)
  1655         if not event.Dragging():
  1733         if not event.Dragging():
  1685     # Refreshes the wire state according to move defined and handle selected
  1763     # Refreshes the wire state according to move defined and handle selected
  1686     def ProcessDragging(self, movex, movey):
  1764     def ProcessDragging(self, movex, movey):
  1687         handle_type, handle = self.Handle
  1765         handle_type, handle = self.Handle
  1688         # A point has been handled
  1766         # A point has been handled
  1689         if handle_type == HANDLE_POINT:
  1767         if handle_type == HANDLE_POINT:
       
  1768             movex = max(-self.Points[handle].x + POINT_RADIUS, movex)
       
  1769             movey = max(-self.Points[handle].y + POINT_RADIUS, movey)
  1690             # Try to connect point to a connector
  1770             # Try to connect point to a connector
  1691             new_pos = wx.Point(self.Points[handle].x + movex, self.Points[handle].y + movey)
  1771             new_pos = wx.Point(self.Points[handle].x + movex, self.Points[handle].y + movey)
  1692             connector = self.Parent.FindBlockConnector(new_pos)
  1772             connector = self.Parent.FindBlockConnector(new_pos)
  1693             if connector:
  1773             if connector:
  1694                 if handle == 0 and self.EndConnected != connector and connector.IsCompatible(self.GetEndConnectedType()):
  1774                 if handle == 0 and self.EndConnected != connector and connector.IsCompatible(self.GetEndConnectedType()):
  1695                     connector.Connect((self, handle))
  1775                     connector.Connect((self, handle))
  1696                     self.SetStartPointDirection(connector.GetDirection())
  1776                     self.SetStartPointDirection(connector.GetDirection())
  1697                     self.ConnectStartPoint(connector.GetPosition(), connector)
  1777                     self.ConnectStartPoint(connector.GetPosition(), connector)
  1698                     self.oldPos = connector.GetPosition()
  1778                     pos = connector.GetPosition()
       
  1779                     movex = pos.x - self.oldPos.x
       
  1780                     movey = pos.y - self.oldPos.y
  1699                     self.Dragging = False
  1781                     self.Dragging = False
  1700                 elif handle != 0 and self.StartConnected != connector and connector.IsCompatible(self.GetStartConnectedType()):
  1782                 elif handle != 0 and self.StartConnected != connector and connector.IsCompatible(self.GetStartConnectedType()):
  1701                     connector.Connect((self, handle))
  1783                     connector.Connect((self, handle))
  1702                     self.SetEndPointDirection(connector.GetDirection())
  1784                     self.SetEndPointDirection(connector.GetDirection())
  1703                     self.ConnectEndPoint(connector.GetPosition(), connector)
  1785                     self.ConnectEndPoint(connector.GetPosition(), connector)
  1704                     self.oldPos = connector.GetPosition()
  1786                     pos = connector.GetPosition()
       
  1787                     movex = pos.x - self.oldPos.x
       
  1788                     movey = pos.y - self.oldPos.y
  1705                     self.Dragging = False
  1789                     self.Dragging = False
  1706                 elif handle == 0:
  1790                 elif handle == 0:
  1707                     self.MoveStartPoint(new_pos)
  1791                     self.MoveStartPoint(new_pos)
  1708                 else:
  1792                 else:
  1709                     self.MoveEndPoint(new_pos)
  1793                     self.MoveEndPoint(new_pos)
  1714                 self.MoveStartPoint(new_pos)
  1798                 self.MoveStartPoint(new_pos)
  1715             else:
  1799             else:
  1716                 if self.EndConnected:
  1800                 if self.EndConnected:
  1717                     self.UnConnectEndPoint()
  1801                     self.UnConnectEndPoint()
  1718                 self.MoveEndPoint(new_pos)
  1802                 self.MoveEndPoint(new_pos)
  1719             return True, True
  1803             return movex, movey
  1720         # A segment has been handled, move a segment
  1804         # A segment has been handled, move a segment
  1721         elif handle_type == HANDLE_SEGMENT:
  1805         elif handle_type == HANDLE_SEGMENT:
  1722             return self.MoveSegment(handle[0], movex, movey)
  1806             return self.MoveSegment(handle[0], movex, movey)
  1723         # Execute the default method for a graphic element
  1807         # Execute the default method for a graphic element
  1724         else:
  1808         else: