graphics/GraphicCommons.py
changeset 249 d8425712acef
parent 243 c5da8b706cde
child 253 d9391572655f
equal deleted inserted replaced
248:f7df265edd54 249:d8425712acef
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 import wx
    25 import wx
    26 from math import *
    26 from math import *
       
    27 from types import *
    27 
    28 
    28 #-------------------------------------------------------------------------------
    29 #-------------------------------------------------------------------------------
    29 #                               Common constants
    30 #                               Common constants
    30 #-------------------------------------------------------------------------------
    31 #-------------------------------------------------------------------------------
    31 
    32 
   307         self.Selected = False
   308         self.Selected = False
   308         self.Highlighted = False
   309         self.Highlighted = False
   309         self.Pos = wx.Point(0, 0)
   310         self.Pos = wx.Point(0, 0)
   310         self.Size = wx.Size(0, 0)
   311         self.Size = wx.Size(0, 0)
   311         self.BoundingBox = wx.Rect(0, 0, 0, 0)
   312         self.BoundingBox = wx.Rect(0, 0, 0, 0)
       
   313         self.Visible = False
   312         self.CurrentCursor = 0
   314         self.CurrentCursor = 0
   313         ResetCursors()
   315         ResetCursors()
       
   316     
       
   317     def TestVisible(self, screen):
       
   318         self.Visible = self.BoundingBox.Intersects(screen)
       
   319     
       
   320     def IsVisible(self):
       
   321         return self.Visible
       
   322     
       
   323     def SpreadCurrent(self):
       
   324         pass
   314     
   325     
   315     def IsOfType(self, type, reference):
   326     def IsOfType(self, type, reference):
   316         return self.Parent.IsOfType(type, reference)
   327         return self.Parent.IsOfType(type, reference)
   317     
   328     
   318     def IsEndType(self, type):
   329     def IsEndType(self, type):
   661     
   672     
   662     # Destructor
   673     # Destructor
   663     def __del__(self):
   674     def __del__(self):
   664         self.Elements = []
   675         self.Elements = []
   665     
   676     
       
   677     def IsVisible(self):
       
   678         for element in self.Elements:
       
   679             if element.IsVisible():
       
   680                 return True
       
   681         return False
       
   682     
   666     # Refresh the list of wire excluded
   683     # Refresh the list of wire excluded
   667     def RefreshWireExclusion(self):
   684     def RefreshWireExclusion(self):
   668         self.WireExcluded = []
   685         self.WireExcluded = []
   669         for element in self.Elements:
   686         for element in self.Elements:
   670             if isinstance(element, Wire):
   687             if isinstance(element, Wire):
   860             self.Edge = edge
   877             self.Edge = edge
   861         else:
   878         else:
   862             self.Negated = False
   879             self.Negated = False
   863             self.Edge = "none"
   880             self.Edge = "none"
   864         self.OneConnected = onlyone
   881         self.OneConnected = onlyone
       
   882         self.Valid = True
       
   883         self.Value = None
   865         self.Pen = wx.BLACK_PEN
   884         self.Pen = wx.BLACK_PEN
   866         self.Errors = {}
   885         self.Errors = {}
   867         self.RefreshNameSize()
   886         self.RefreshNameSize()
       
   887     
       
   888     def Flush(self):
       
   889         self.ParentBlock = None
       
   890         for wire, handle in self.Wires:
       
   891             wire.Flush()
       
   892         self.Wires = []
   868     
   893     
   869     # Returns the RedrawRect
   894     # Returns the RedrawRect
   870     def GetRedrawRect(self, movex = 0, movey = 0):
   895     def GetRedrawRect(self, movex = 0, movey = 0):
   871         parent_pos = self.ParentBlock.GetPosition()
   896         parent_pos = self.ParentBlock.GetPosition()
   872         x = min(parent_pos[0] + self.Pos.x, parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE)
   897         x = min(parent_pos[0] + self.Pos.x, parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE)
   939     # Changes the connector name
   964     # Changes the connector name
   940     def SetName(self, name):
   965     def SetName(self, name):
   941         self.Name = name
   966         self.Name = name
   942         self.RefreshNameSize()
   967         self.RefreshNameSize()
   943 
   968 
   944     def SetValue(self, value):
   969     def RefreshValue(self):
       
   970         self.Value = self.ReceivingCurrent()
       
   971     
       
   972     def MarkAsInvalid(self):
       
   973         self.Valid = False
       
   974     
       
   975     def ReceivingCurrent(self):
       
   976         current = False
   945         for wire, handle in self.Wires:
   977         for wire, handle in self.Wires:
   946             wire.SetValue(value)
   978             value = wire.GetValue()
       
   979             if isinstance(value, BooleanType):
       
   980                 current |= wire.GetValue()
       
   981         return current
       
   982     
       
   983     def SpreadCurrent(self, spreading):
       
   984         for wire, handle in self.Wires:
       
   985             wire.SetValue(spreading)
   947     
   986     
   948     # Changes the connector name size
   987     # Changes the connector name size
   949     def RefreshNameSize(self):
   988     def RefreshNameSize(self):
   950         if self.Name != "":
   989         if self.Name != "":
   951             dc = wx.ClientDC(self.ParentBlock.Parent)
   990             dc = wx.ClientDC(self.ParentBlock.Parent)
  1103             self.Negated = False
  1142             self.Negated = False
  1104     
  1143     
  1105     # Tests if the point given is near from the end point of this connector
  1144     # Tests if the point given is near from the end point of this connector
  1106     def TestPoint(self, pt, direction = None, exclude = True):
  1145     def TestPoint(self, pt, direction = None, exclude = True):
  1107         parent_pos = self.ParentBlock.GetPosition()
  1146         parent_pos = self.ParentBlock.GetPosition()
  1108         if not (len(self.Wires) > 0 and self.OneConnected and exclude):
  1147         if (not (len(self.Wires) > 0 and self.OneConnected and exclude) or self.Type == "BOOL")\
  1109             if direction is None or self.Direction == direction:
  1148             and direction is None or self.Direction == direction:
  1110                 # Calculate a square around the end point of this connector
  1149             # Calculate a square around the end point of this connector
  1111                 x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1150             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1112                 y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1151             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1113                 width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
  1152             width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
  1114                 height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
  1153             height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
  1115                 rect = wx.Rect(x, y, width, height)
  1154             rect = wx.Rect(x, y, width, height)
  1116                 return rect.InsideXY(pt.x, pt.y)
  1155             return rect.InsideXY(pt.x, pt.y)
  1117         return False
  1156         return False
  1118     
  1157     
  1119     # Draws the highlightment of this element if it is highlighted
  1158     # Draws the highlightment of this element if it is highlighted
  1120     def DrawHighlightment(self, dc):
  1159     def DrawHighlightment(self, dc):
  1121         dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
  1160         dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
  1150     def Draw(self, dc):
  1189     def Draw(self, dc):
  1151         if len(self.Errors) > 0:
  1190         if len(self.Errors) > 0:
  1152             dc.SetPen(wx.RED_PEN)
  1191             dc.SetPen(wx.RED_PEN)
  1153             dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
  1192             dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
  1154         else:
  1193         else:
  1155             dc.SetPen(self.Pen)
  1194             if not self.Valid:
       
  1195                 dc.SetPen(wx.RED_PEN)
       
  1196             elif isinstance(self.Value, BooleanType) and self.Value:
       
  1197                 dc.SetPen(wx.GREEN_PEN)
       
  1198             else:
       
  1199                 dc.SetPen(self.Pen)
  1156             dc.SetBrush(wx.WHITE_BRUSH)
  1200             dc.SetBrush(wx.WHITE_BRUSH)
  1157         parent_pos = self.ParentBlock.GetPosition()
  1201         parent_pos = self.ParentBlock.GetPosition()
  1158         
  1202         
  1159         if getattr(dc, "printing", False):
  1203         if getattr(dc, "printing", False):
  1160             name_size = dc.GetTextExtent(self.Name)
  1204             name_size = dc.GetTextExtent(self.Name)
  1224             self.Points = []
  1268             self.Points = []
  1225             self.Segments = []
  1269             self.Segments = []
  1226         self.SelectedSegment = None
  1270         self.SelectedSegment = None
  1227         self.Valid = True
  1271         self.Valid = True
  1228         self.Value = None
  1272         self.Value = None
       
  1273         self.ValueSize = None
  1229         self.OverStart = False
  1274         self.OverStart = False
  1230         self.OverEnd = False
  1275         self.OverEnd = False
  1231         self.ComputingType = False
  1276         self.ComputingType = False
  1232     
  1277         parent_font = parent.GetFont()
  1233     # Destructor of a wire
  1278         self.Font = wx.Font(parent_font.GetPointSize() * 0.75, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = parent_font.GetFaceName())
  1234     def __del__(self):
  1279         
       
  1280     def Flush(self):
  1235         self.StartConnected = None
  1281         self.StartConnected = None
  1236         self.EndConnected = None
  1282         self.EndConnected = None
  1237     
  1283     
  1238     # Returns the RedrawRect
  1284     # Returns the RedrawRect
  1239     def GetRedrawRect(self, movex = 0, movey = 0):
  1285     def GetRedrawRect(self, movex = 0, movey = 0):
  1240         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1286         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1241         if self.StartConnected:
  1287         if self.StartConnected:
  1242             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
  1288             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
  1243         if self.EndConnected:
  1289         if self.EndConnected:
  1244             rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey))
  1290             rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey))
       
  1291         if self.ValueSize is not None:
       
  1292             width, height = self.ValueSize
       
  1293             width, height = self.ValueSize
       
  1294             if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4:
       
  1295                 x = self.Points[0].x + width * self.StartPoint[1][0] / 2
       
  1296                 y = self.Points[0].y + (height * self.StartPoint[1][1] - 1) / 2
       
  1297                 rect = rect.Union(wx.Rect(x, y, width, height))
       
  1298                 x = self.Points[-1].x + width * self.EndPoint[1][0] / 2
       
  1299                 y = self.Points[-1].y + (height * self.EndPoint[1][1] - 1) / 2
       
  1300                 rect = rect.Union(wx.Rect(x, y, width, height))
       
  1301             else:
       
  1302                 middle = len(self.Segments) / 2 + len(self.Segments) % 2 - 1
       
  1303                 x = self.Points[middle].x - width / 2
       
  1304                 y = self.Points[middle].y - height / 2
       
  1305                 rect = rect.Union(wx.Rect(x, y, width, height))
  1245         return rect
  1306         return rect
  1246     
  1307     
  1247     # Forbids to change the wire position
  1308     # Forbids to change the wire position
  1248     def SetPosition(x, y):
  1309     def SetPosition(x, y):
  1249         pass
  1310         pass
  1313         elif self.EndConnected:
  1374         elif self.EndConnected:
  1314             return True
  1375             return True
  1315         return False
  1376         return False
  1316     
  1377     
  1317     def SetValue(self, value):
  1378     def SetValue(self, value):
  1318         self.Value = value
  1379         if value is not None and not isinstance(value, BooleanType):
       
  1380             if isinstance(value, StringType):
       
  1381                 value = "\"%s\""%value
       
  1382             else:
       
  1383                 value = str(value)
       
  1384             if len(value) > 4:
       
  1385                 value = value[:4] + "_"
       
  1386         if self.Value != value:
       
  1387             self.Value = value
       
  1388             if isinstance(self.Value, StringType):
       
  1389                 dc = wx.ClientDC(self.Parent)
       
  1390                 dc.SetFont(self.Font)
       
  1391                 self.ValueSize = dc.GetTextExtent(self.Value)
       
  1392             else:
       
  1393                 self.ValueSize = None
       
  1394             if self.StartConnected:
       
  1395                 self.StartConnected.RefreshValue()
       
  1396             if self.EndConnected:
       
  1397                 self.EndConnected.RefreshValue()
       
  1398             self.Refresh()
       
  1399             if isinstance(value, BooleanType):
       
  1400                 block = self.StartConnected.GetParentBlock()
       
  1401                 block.SpreadCurrent()
       
  1402     
       
  1403     def GetValue(self):
       
  1404         return self.Value
  1319     
  1405     
  1320     # Unconnect the start and end points
  1406     # Unconnect the start and end points
  1321     def Clean(self):
  1407     def Clean(self):
  1322         if self.StartConnected:
  1408         if self.StartConnected:
  1323             self.UnConnectStartPoint()
  1409             self.UnConnectStartPoint()
  1360     
  1446     
  1361     # Select a segment and not the whole wire. It's useful for Ladder Diagram
  1447     # Select a segment and not the whole wire. It's useful for Ladder Diagram
  1362     def MarkAsInvalid(self):
  1448     def MarkAsInvalid(self):
  1363         self.Valid = False
  1449         self.Valid = False
  1364         if self.StartConnected:
  1450         if self.StartConnected:
  1365             self.StartConnected.SetPen(wx.RED_PEN)
  1451             self.StartConnected.MarkAsInvalid()
  1366         if self.EndConnected:
  1452         if self.EndConnected:
  1367             self.EndConnected.SetPen(wx.RED_PEN)
  1453             self.EndConnected.MarkAsInvalid()
  1368     
  1454     
  1369     # Reinitialize the wire points
  1455     # Reinitialize the wire points
  1370     def ResetPoints(self):
  1456     def ResetPoints(self):
  1371         if self.StartPoint and self.EndPoint:
  1457         if self.StartPoint and self.EndPoint:
  1372             self.Points = [self.StartPoint[0], self.EndPoint[0]]
  1458             self.Points = [self.StartPoint[0], self.EndPoint[0]]
  1748                 width = lastwidth
  1834                 width = lastwidth
  1749             if height != lastheight and lastheight == self.Size.height:
  1835             if height != lastheight and lastheight == self.Size.height:
  1750                 height = lastheight
  1836                 height = lastheight
  1751             # Calculate the real points from the new size, it's important for
  1837             # Calculate the real points from the new size, it's important for
  1752             # keeping a proportionality in the points position with the size
  1838             # keeping a proportionality in the points position with the size
  1753             # duringa resize dragging
  1839             # during a resize dragging
  1754             for i, point in enumerate(self.RealPoints):
  1840             for i, point in enumerate(self.RealPoints):
  1755                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  1841                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  1756                     point[0] = point[0] * width / float(max(lastwidth, 1))
  1842                     point[0] = point[0] * width / float(max(lastwidth, 1))
  1757                     point[1] = point[1] * height / float(max(lastheight, 1))
  1843                     point[1] = point[1] * height / float(max(lastheight, 1))
  1758             # Calculate the correct position of the points from real points
  1844             # Calculate the correct position of the points from real points
  2091             self.EndConnected.Draw(dc)
  2177             self.EndConnected.Draw(dc)
  2092         
  2178         
  2093     # Draws the wire lines and points
  2179     # Draws the wire lines and points
  2094     def Draw(self, dc):
  2180     def Draw(self, dc):
  2095         Graphic_Element.Draw(self, dc)
  2181         Graphic_Element.Draw(self, dc)
  2096         if self.Valid:
  2182         if not self.Valid:
       
  2183             dc.SetPen(wx.RED_PEN)
       
  2184         elif isinstance(self.Value, BooleanType) and self.Value:
       
  2185             dc.SetPen(wx.GREEN_PEN)
       
  2186         else:
  2097             dc.SetPen(wx.BLACK_PEN)
  2187             dc.SetPen(wx.BLACK_PEN)
  2098         else:
       
  2099             dc.SetPen(wx.RED_PEN)
       
  2100         dc.SetBrush(wx.BLACK_BRUSH)
  2188         dc.SetBrush(wx.BLACK_BRUSH)
  2101         # Draw the start and end points if they are not connected or the mouse is over them
  2189         # Draw the start and end points if they are not connected or the mouse is over them
  2102         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2190         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2103             dc.DrawCircle(self.Points[0].x, self.Points[0].y, POINT_RADIUS)
  2191             dc.DrawCircle(self.Points[0].x, self.Points[0].y, POINT_RADIUS)
  2104         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2192         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2105             dc.DrawCircle(self.Points[-1].x, self.Points[-1].y, POINT_RADIUS)
  2193             dc.DrawCircle(self.Points[-1].x, self.Points[-1].y, POINT_RADIUS)
  2106         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2194         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2107         dc.DrawLines(self.Points)
  2195         dc.DrawLines(self.Points)
  2108         dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
  2196         dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
  2109         # Draw the segment selected in red
  2197         # Draw the segment selected in red
  2110         if self.SelectedSegment != None:
  2198         if self.SelectedSegment is not None:
  2111             dc.SetPen(wx.RED_PEN)
  2199             dc.SetPen(wx.RED_PEN)
  2112             dc.DrawLine(self.Points[self.SelectedSegment].x, self.Points[self.SelectedSegment].y,
  2200             dc.DrawLine(self.Points[self.SelectedSegment].x, self.Points[self.SelectedSegment].y,
  2113                         self.Points[self.SelectedSegment + 1].x, self.Points[self.SelectedSegment + 1].y)
  2201                         self.Points[self.SelectedSegment + 1].x, self.Points[self.SelectedSegment + 1].y)
  2114             if self.SelectedSegment == len(self.Segments) - 1:
  2202             if self.SelectedSegment == len(self.Segments) - 1:
  2115                 dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
  2203                 dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
       
  2204         if self.Value is not None and not isinstance(self.Value, BooleanType):
       
  2205             dc.SetFont(self.Font)
       
  2206             dc.SetTextForeground(wx.NamedColour("purple"))
       
  2207             width, height = self.ValueSize
       
  2208             if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4:
       
  2209                 x = self.Points[0].x + width * self.StartPoint[1][0] / 2
       
  2210                 y = self.Points[0].y + height * (self.StartPoint[1][1] - 1) / 2
       
  2211                 dc.DrawText(self.Value, x, y)
       
  2212                 x = self.Points[-1].x + width * self.EndPoint[1][0] / 2
       
  2213                 y = self.Points[-1].y + height * (self.EndPoint[1][1] - 1) / 2
       
  2214                 dc.DrawText(self.Value, x, y)
       
  2215             else:
       
  2216                 middle = len(self.Segments) / 2 + len(self.Segments) % 2 - 1
       
  2217                 x = (self.Points[middle].x + self.Points[middle + 1].x - width) / 2
       
  2218                 y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
       
  2219                 dc.DrawText(self.Value, x, y)
       
  2220             dc.SetFont(self.Parent.GetFont())
       
  2221             dc.SetTextForeground(wx.BLACK)
  2116 
  2222 
  2117 
  2223 
  2118 #-------------------------------------------------------------------------------
  2224 #-------------------------------------------------------------------------------
  2119 #                           Graphic comment element
  2225 #                           Graphic comment element
  2120 #-------------------------------------------------------------------------------
  2226 #-------------------------------------------------------------------------------
  2281                         else:
  2387                         else:
  2282                             linetext = word
  2388                             linetext = word
  2283                     y += wordheight + 5
  2389                     y += wordheight + 5
  2284             if y + wordheight > self.Pos.y + self.Size[1] - 10:
  2390             if y + wordheight > self.Pos.y + self.Size[1] - 10:
  2285                 break
  2391                 break
       
  2392