graphics/GraphicCommons.py
changeset 563 3f92a5e18804
parent 554 08c26c62f5a7
child 566 6014ef82a98a
equal deleted inserted replaced
562:0ce12552cf36 563:3f92a5e18804
   224 TYPE_TRANSLATOR = {"TIME": generate_time,
   224 TYPE_TRANSLATOR = {"TIME": generate_time,
   225                    "DATE": generate_date,
   225                    "DATE": generate_date,
   226                    "DT": generate_datetime,
   226                    "DT": generate_datetime,
   227                    "TOD": generate_timeofday}
   227                    "TOD": generate_timeofday}
   228 
   228 
       
   229 def MiterPen(colour, width=1, style=wx.SOLID):
       
   230     pen = wx.Pen(colour, width, style)
       
   231     pen.SetJoin(wx.JOIN_MITER)
       
   232     pen.SetCap(wx.CAP_PROJECTING)
       
   233     return pen
       
   234 
   229 #-------------------------------------------------------------------------------
   235 #-------------------------------------------------------------------------------
   230 #                            Debug Data Consumer Class
   236 #                            Debug Data Consumer Class
   231 #-------------------------------------------------------------------------------
   237 #-------------------------------------------------------------------------------
   232 
   238 
   233 class DebugDataConsumer:
   239 class DebugDataConsumer:
   437 
   443 
   438     # Method that erase the last box and draw the new box
   444     # Method that erase the last box and draw the new box
   439     def Redraw(self, dc = None):
   445     def Redraw(self, dc = None):
   440         if not dc:
   446         if not dc:
   441             dc = self.drawingSurface.GetLogicalDC()
   447             dc = self.drawingSurface.GetLogicalDC()
       
   448         scalex, scaley = dc.GetUserScale()
       
   449         dc.SetUserScale(1, 1)
   442         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   450         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   443         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   451         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   444         dc.SetLogicalFunction(wx.XOR)
   452         dc.SetLogicalFunction(wx.XOR)
   445         if self.lastBox:
   453         if self.lastBox:
   446             # Erase last box
   454             # Erase last box
   447             dc.DrawRectangle(self.lastBox.x, self.lastBox.y, self.lastBox.width,
   455             dc.DrawRectangle(self.lastBox.x * scalex, self.lastBox.y * scaley, 
   448                 self.lastBox.height)
   456                              self.lastBox.width * scalex, self.lastBox.height * scaley)
   449         if self.currentBox:
   457         if self.currentBox:
   450             # Draw current box
   458             # Draw current box
   451             dc.DrawRectangle(self.currentBox.x, self.currentBox.y, self.currentBox.width,
   459             dc.DrawRectangle(self.currentBox.x * scalex, self.currentBox.y * scaley, 
   452                 self.currentBox.height)
   460                              self.currentBox.width * scalex, self.currentBox.height * scaley)
       
   461         dc.SetUserScale(scalex, scaley)
   453     
   462     
   454     # Erase last box
   463     # Erase last box
   455     def Erase(self, dc = None):
   464     def Erase(self, dc = None):
   456         if not dc:
   465         if not dc:
   457             dc = self.drawingSurface.GetLogicalDC()
   466             dc = self.drawingSurface.GetLogicalDC()
       
   467         scalex, scaley = dc.GetUserScale()
       
   468         dc.SetUserScale(1, 1)
   458         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   469         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   459         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   470         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   460         dc.SetLogicalFunction(wx.XOR)
   471         dc.SetLogicalFunction(wx.XOR)
   461         if self.lastBox:
   472         if self.lastBox:
   462             dc.DrawRectangle(self.lastBox.x, self.lastBox.y, self.lastBox.width,
   473             dc.DrawRectangle(self.lastBox.x * scalex, self.lastBox.y * scaley, 
   463                 self.lastBox.height)
   474                              self.lastBox.width * scalex, self.lastBox.height * scalex)
   464     
   475         dc.SetUserScale(scalex, scaley)
       
   476 
   465     # Draw current box
   477     # Draw current box
   466     def Draw(self, dc = None):
   478     def Draw(self, dc = None):
   467         if not dc:
   479         if not dc:
   468             dc = self.drawingSurface.GetLogicalDC()
   480             dc = self.drawingSurface.GetLogicalDC()
       
   481         scalex, scaley = dc.GetUserScale()
       
   482         dc.SetUserScale(1, 1)
   469         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   483         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   470         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   484         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   471         dc.SetLogicalFunction(wx.XOR)
   485         dc.SetLogicalFunction(wx.XOR)
   472         if self.currentBox:
   486         if self.currentBox:
   473             # Draw current box
   487             # Draw current box
   474             dc.DrawRectangle(self.currentBox.x, self.currentBox.y, self.currentBox.width,
   488             dc.DrawRectangle(self.currentBox.x * scalex, self.currentBox.y * scaley, 
   475                 self.currentBox.height)
   489                              self.currentBox.width * scalex, self.currentBox.height * scaley)
       
   490         dc.SetUserScale(scalex, scaley)
   476 
   491 
   477 #-------------------------------------------------------------------------------
   492 #-------------------------------------------------------------------------------
   478 #                               Viewer ToolTip
   493 #                               Viewer ToolTip
   479 #-------------------------------------------------------------------------------
   494 #-------------------------------------------------------------------------------
   480 
   495 
   504             self.Refresh()
   519             self.Refresh()
   505         
   520         
   506     def OnPaint(self, event):
   521     def OnPaint(self, event):
   507         dc = wx.AutoBufferedPaintDC(self)
   522         dc = wx.AutoBufferedPaintDC(self)
   508         dc.Clear()
   523         dc.Clear()
   509         dc.SetPen(wx.BLACK_PEN)
   524         dc.SetPen(MiterPen(wx.BLACK))
   510         dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170)))
   525         dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170)))
   511         dc.BeginDrawing()
   526         dc.BeginDrawing()
   512         w, h = dc.GetTextExtent(self.Tip)
   527         w, h = dc.GetTextExtent(self.Tip)
   513         dc.DrawRectangle(0, 0, w + 4, h + 4)
   528         dc.DrawRectangle(0, 0, w + 4, h + 4)
   514         dc.DrawText(self.Tip, 2, 2)
   529         dc.DrawText(self.Tip, 2, 2)
   662     def GetBoundingBox(self):
   677     def GetBoundingBox(self):
   663         return self.BoundingBox
   678         return self.BoundingBox
   664     
   679     
   665     # Returns the RedrawRect
   680     # Returns the RedrawRect
   666     def GetRedrawRect(self, movex = 0, movey = 0):
   681     def GetRedrawRect(self, movex = 0, movey = 0):
       
   682         dc = self.Parent.GetLogicalDC()
       
   683         scalex, scaley = dc.GetUserScale()
   667         rect = wx.Rect()
   684         rect = wx.Rect()
   668         rect.x = self.BoundingBox.x - HANDLE_SIZE - 2 - abs(movex)
   685         rect.x = self.BoundingBox.x - int(HANDLE_SIZE / scalex) - 3 - abs(movex)
   669         rect.y = self.BoundingBox.y - HANDLE_SIZE - 2 - abs(movey)
   686         rect.y = self.BoundingBox.y - int(HANDLE_SIZE / scaley) - 3 - abs(movey)
   670         rect.width = self.BoundingBox.width + 2 * (HANDLE_SIZE + abs(movex)) + 4
   687         rect.width = self.BoundingBox.width + 2 * (int(HANDLE_SIZE / scalex) + abs(movex) + 1) + 4
   671         rect.height = self.BoundingBox.height + 2 * (HANDLE_SIZE + abs(movey)) + 4
   688         rect.height = self.BoundingBox.height + 2 * (int(HANDLE_SIZE / scaley) + abs(movey) + 1) + 4
   672         return rect
   689         return rect
   673     
   690     
   674     def Refresh(self, rect = None):
   691     def Refresh(self, rect = None):
   675         if self.Visible:
   692         if self.Visible:
   676             if rect is not None:
   693             if rect is not None:
   687     def SetHighlighted(self, highlighted):
   704     def SetHighlighted(self, highlighted):
   688         self.Highlighted = highlighted
   705         self.Highlighted = highlighted
   689         self.Refresh()
   706         self.Refresh()
   690     
   707     
   691     # Test if the point is on a handle of this element
   708     # Test if the point is on a handle of this element
   692     def TestHandle(self, pt):
   709     def TestHandle(self, event):
   693         extern_rect = wx.Rect(self.BoundingBox.x - HANDLE_SIZE - 2, self.BoundingBox.y - HANDLE_SIZE - 2, 
   710         dc = self.Parent.GetLogicalDC()
   694             self.BoundingBox.width + 2 * HANDLE_SIZE + 4, self.BoundingBox.height + 2 * HANDLE_SIZE + 4)
   711         scalex, scaley = dc.GetUserScale()
   695         intern_rect = wx.Rect(self.BoundingBox.x - 2, self.BoundingBox.y - 2, 
   712         pos = event.GetPosition()
   696             self.BoundingBox.width + 4, self.BoundingBox.height + 4)
   713         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
       
   714         
       
   715         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
       
   716         center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
       
   717         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
       
   718         
       
   719         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
       
   720         middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
       
   721         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
       
   722         
       
   723         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
       
   724         intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE)
       
   725         
   697         # Verify that this element is selected
   726         # Verify that this element is selected
   698         if self.Selected and extern_rect.InsideXY(pt.x, pt.y) and not intern_rect.InsideXY(pt.x, pt.y):
   727         if self.Selected and extern_rect.InsideXY(pt.x, pt.y) and not intern_rect.InsideXY(pt.x, pt.y):
   699             # Find if point is on a handle horizontally
   728             # Find if point is on a handle horizontally
   700             if self.BoundingBox.x - HANDLE_SIZE - 2 <= pt.x < self.BoundingBox.x - 2:
   729             if left <= pt.x < left + HANDLE_SIZE:
   701                 handle_x = 1
   730                 handle_x = 1
   702             elif self.BoundingBox.x + (self.BoundingBox.width - HANDLE_SIZE) / 2 <= pt.x < self.BoundingBox.x + (self.BoundingBox.width + HANDLE_SIZE) / 2:
   731             elif center <= pt.x < center + HANDLE_SIZE:
   703                 handle_x = 2
   732                 handle_x = 2
   704             elif self.BoundingBox.x + self.BoundingBox.width + 2 <= pt.x < self.BoundingBox.x + self.BoundingBox.width + HANDLE_SIZE + 2:
   733             elif right <= pt.x < right + HANDLE_SIZE:
   705                 handle_x = 3
   734                 handle_x = 3
   706             else:
   735             else:
   707                 handle_x = 0
   736                 handle_x = 0
   708             # Find if point is on a handle vertically
   737             # Find if point is on a handle vertically
   709             if self.BoundingBox.y - HANDLE_SIZE - 2 <= pt.y < self.BoundingBox.y - 2:
   738             if top <= pt.y < top + HANDLE_SIZE:
   710                 handle_y = 1
   739                 handle_y = 1
   711             elif self.BoundingBox.y + (self.BoundingBox.height - HANDLE_SIZE) / 2 <= pt.y < self.BoundingBox.y + (self.BoundingBox.height + HANDLE_SIZE) / 2:
   740             elif middle <= pt.y < middle + HANDLE_SIZE:
   712                 handle_y = 2
   741                 handle_y = 2
   713             elif self.BoundingBox.y + self.BoundingBox.height - 2 <= pt.y < self.BoundingBox.y + self.BoundingBox.height + HANDLE_SIZE + 2:
   742             elif bottom <= pt.y < bottom + HANDLE_SIZE:
   714                 handle_y = 3
   743                 handle_y = 3
   715             else:
   744             else:
   716                 handle_y = 0
   745                 handle_y = 0
   717             # Verify that the result is valid
   746             # Verify that the result is valid
   718             if (handle_x, handle_y) in VALID_HANDLES:
   747             if (handle_x, handle_y) in VALID_HANDLES:
   721     
   750     
   722     # Method called when a LeftDown event have been generated
   751     # Method called when a LeftDown event have been generated
   723     def OnLeftDown(self, event, dc, scaling):
   752     def OnLeftDown(self, event, dc, scaling):
   724         pos = event.GetLogicalPosition(dc)
   753         pos = event.GetLogicalPosition(dc)
   725         # Test if an handle have been clicked
   754         # Test if an handle have been clicked
   726         handle = self.TestHandle(pos)
   755         handle = self.TestHandle(event)
   727         # Find which type of handle have been clicked,
   756         # Find which type of handle have been clicked,
   728         # Save a resize event and change the cursor
   757         # Save a resize event and change the cursor
   729         cursor = HANDLE_CURSORS.get(handle, 1)
   758         cursor = HANDLE_CURSORS.get(handle, 1)
   730         wx.CallAfter(self.Parent.SetCurrentCursor, cursor)
   759         wx.CallAfter(self.Parent.SetCurrentCursor, cursor)
   731         if cursor > 1:
   760         if cursor > 1:
   790                 return dragx, dragy
   819                 return dragx, dragy
   791             return movex, movey
   820             return movex, movey
   792         # If cursor just pass over the element, changes the cursor if it is on a handle
   821         # If cursor just pass over the element, changes the cursor if it is on a handle
   793         else:
   822         else:
   794             pos = event.GetLogicalPosition(dc)
   823             pos = event.GetLogicalPosition(dc)
   795             handle = self.TestHandle(pos)
   824             handle = self.TestHandle(event)
   796             # Find which type of handle have been clicked,
   825             # Find which type of handle have been clicked,
   797             # Save a resize event and change the cursor
   826             # Save a resize event and change the cursor
   798             cursor = HANDLE_CURSORS.get(handle, 0)
   827             cursor = HANDLE_CURSORS.get(handle, 0)
   799             wx.CallAfter(self.Parent.SetCurrentCursor, cursor)
   828             wx.CallAfter(self.Parent.SetCurrentCursor, cursor)
   800             return 0, 0
   829             return 0, 0
   912     def RefreshModel(self, move=True):
   941     def RefreshModel(self, move=True):
   913         pass
   942         pass
   914     
   943     
   915     # Draws the highlightment of this element if it is highlighted (can be overwritten)
   944     # Draws the highlightment of this element if it is highlighted (can be overwritten)
   916     def DrawHighlightment(self, dc):
   945     def DrawHighlightment(self, dc):
   917         dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
   946         scalex, scaley = dc.GetUserScale()
       
   947         dc.SetUserScale(1, 1)
       
   948         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   918         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
   949         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
   919         dc.SetLogicalFunction(wx.AND)
   950         dc.SetLogicalFunction(wx.AND)
   920         dc.DrawRectangle(self.Pos.x - 2, self.Pos.y - 2, self.Size.width + 5, self.Size.height + 5)
   951         dc.DrawRectangle(int(round((self.Pos.x - 1) * scalex)) - 2, 
       
   952                          int(round((self.Pos.y - 1) * scaley)) - 2, 
       
   953                          int(round((self.Size.width + 3) * scalex)) + 5, 
       
   954                          int(round((self.Size.height + 3) * scaley)) + 5)
   921         dc.SetLogicalFunction(wx.COPY)
   955         dc.SetLogicalFunction(wx.COPY)
       
   956         dc.SetUserScale(scalex, scaley)
   922     
   957     
   923     # Draws the handles of this element if it is selected
   958     # Draws the handles of this element if it is selected
   924     def Draw(self, dc):
   959     def Draw(self, dc):
   925         if not getattr(dc, "printing", False):
   960         if not getattr(dc, "printing", False):
   926             if self.Highlighted:
   961             if self.Highlighted:
   927                 self.DrawHighlightment(dc)
   962                 self.DrawHighlightment(dc)
   928             if self.Selected:
   963             if self.Selected:
   929                 dc.SetPen(wx.BLACK_PEN)
   964                 scalex, scaley = dc.GetUserScale()
       
   965                 dc.SetUserScale(1, 1)
       
   966                 dc.SetPen(MiterPen(wx.BLACK))
   930                 dc.SetBrush(wx.BLACK_BRUSH)
   967                 dc.SetBrush(wx.BLACK_BRUSH)
   931                 dc.DrawRectangle(self.BoundingBox.x - HANDLE_SIZE - 2, self.BoundingBox.y - HANDLE_SIZE - 2, HANDLE_SIZE, HANDLE_SIZE)
   968                 
   932                 dc.DrawRectangle(self.BoundingBox.x + (self.BoundingBox.width - HANDLE_SIZE) / 2,
   969                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   933                     self.BoundingBox.y - HANDLE_SIZE - 2, HANDLE_SIZE, HANDLE_SIZE)
   970                 center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   934                 dc.DrawRectangle(self.BoundingBox.x + self.BoundingBox.width + 2, 
   971                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   935                     self.BoundingBox.y - HANDLE_SIZE - 2, HANDLE_SIZE, HANDLE_SIZE)
   972                 
   936                 dc.DrawRectangle(self.BoundingBox.x + self.BoundingBox.width + 2, 
   973                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   937                     self.BoundingBox.y + (self.BoundingBox.height - HANDLE_SIZE) / 2, HANDLE_SIZE, HANDLE_SIZE)
   974                 middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   938                 dc.DrawRectangle(self.BoundingBox.x + self.BoundingBox.width + 2, 
   975                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   939                     self.BoundingBox.y + self.BoundingBox.height + 2, HANDLE_SIZE, HANDLE_SIZE)
   976                 
   940                 dc.DrawRectangle(self.BoundingBox.x + (self.BoundingBox.width - HANDLE_SIZE) / 2, 
   977                 for x, y in [(left, top), (center, top), (right, top),
   941                     self.BoundingBox.y + self.BoundingBox.height + 2, HANDLE_SIZE, HANDLE_SIZE)
   978                              (left, middle), (right, middle),
   942                 dc.DrawRectangle(self.BoundingBox.x - HANDLE_SIZE - 2, self.BoundingBox.y + self.BoundingBox.height + 2, HANDLE_SIZE, HANDLE_SIZE)
   979                              (left, bottom), (center, bottom), (right, bottom)]:
   943                 dc.DrawRectangle(self.BoundingBox.x - HANDLE_SIZE - 2, self.BoundingBox.y + (self.BoundingBox.height - HANDLE_SIZE) / 2, HANDLE_SIZE, HANDLE_SIZE)
   980                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
       
   981                 
       
   982                 dc.SetUserScale(scalex, scaley)
   944 
   983 
   945 
   984 
   946 #-------------------------------------------------------------------------------
   985 #-------------------------------------------------------------------------------
   947 #                           Group of graphic elements
   986 #                           Group of graphic elements
   948 #-------------------------------------------------------------------------------
   987 #-------------------------------------------------------------------------------
  1543             return rect.InsideXY(pt.x, pt.y)
  1582             return rect.InsideXY(pt.x, pt.y)
  1544         return False
  1583         return False
  1545     
  1584     
  1546     # Draws the highlightment of this element if it is highlighted
  1585     # Draws the highlightment of this element if it is highlighted
  1547     def DrawHighlightment(self, dc):
  1586     def DrawHighlightment(self, dc):
  1548         dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
  1587         scalex, scaley = dc.GetUserScale()
       
  1588         dc.SetUserScale(1, 1)
       
  1589         pen = MiterPen(HIGHLIGHTCOLOR, 2 * scalex + 5)
       
  1590         pen.SetCap(wx.CAP_BUTT)
       
  1591         dc.SetPen(pen)
  1549         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1592         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1550         dc.SetLogicalFunction(wx.AND)
  1593         dc.SetLogicalFunction(wx.AND)
  1551         parent_pos = self.ParentBlock.GetPosition()
  1594         parent_pos = self.ParentBlock.GetPosition()
  1552         posx = parent_pos[0] + self.Pos.x
  1595         posx = parent_pos[0] + self.Pos.x
  1553         posy = parent_pos[1] + self.Pos.y
  1596         posy = parent_pos[1] + self.Pos.y
  1554         width = CONNECTOR_SIZE
  1597         xstart = parent_pos[0] + self.Pos.x 
  1555         height = CONNECTOR_SIZE
  1598         ystart = parent_pos[1] + self.Pos.y
  1556         if self.Direction[0] < 0:
  1599         if self.Direction[0] < 0:
  1557             posx += CONNECTOR_SIZE * self.Direction[0]
  1600             xstart += 1
  1558         elif self.Direction[0] == 0:
       
  1559             posx -= 2
       
  1560             width = 5
       
  1561         if self.Direction[1] < 0:
  1601         if self.Direction[1] < 0:
  1562             posy += CONNECTOR_SIZE * self.Direction[1]
  1602             ystart += 1
  1563         elif self.Direction[1] == 0:
  1603         xend = xstart + CONNECTOR_SIZE * self.Direction[0]
  1564             posy -= 2
  1604         yend = ystart + CONNECTOR_SIZE * self.Direction[1]
  1565             height = 5
  1605         dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley), 
  1566         dc.DrawRectangle(posx, posy, width, height)
  1606                     round(xend * scalex), round(yend * scaley))
  1567         dc.SetLogicalFunction(wx.COPY)
  1607         dc.SetLogicalFunction(wx.COPY)
       
  1608         dc.SetUserScale(scalex, scaley)
  1568     
  1609     
  1569     def AddError(self, infos, start, end):
  1610     def AddError(self, infos, start, end):
  1570         if len(infos) == 0:
  1611         if len(infos) == 0:
  1571             for wire, handle in self.Wires:
  1612             for wire, handle in self.Wires:
  1572                 wire.SetValid(False)
  1613                 wire.SetValid(False)
  1574             self.Errors[infos[0]] = (start, end)
  1615             self.Errors[infos[0]] = (start, end)
  1575     
  1616     
  1576     # Draws the connector
  1617     # Draws the connector
  1577     def Draw(self, dc):
  1618     def Draw(self, dc):
  1578         if self.Selected:
  1619         if self.Selected:
  1579             dc.SetPen(wx.Pen(wx.BLUE, 3))
  1620             dc.SetPen(MiterPen(wx.BLUE, 3))
  1580             dc.SetBrush(wx.WHITE_BRUSH)
  1621             dc.SetBrush(wx.WHITE_BRUSH)
  1581         elif len(self.Errors) > 0:
  1622         elif len(self.Errors) > 0:
  1582             dc.SetPen(wx.RED_PEN)
  1623             dc.SetPen(MiterPen(wx.RED))
  1583             dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
  1624             dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
  1584         else:
  1625         else:
  1585             if not self.Valid:
  1626             if not self.Valid:
  1586                 dc.SetPen(wx.RED_PEN)
  1627                 dc.SetPen(MiterPen(wx.RED))
  1587             elif isinstance(self.Value, BooleanType) and self.Value:
  1628             elif isinstance(self.Value, BooleanType) and self.Value:
  1588                 if self.Forced:
  1629                 if self.Forced:
  1589                     dc.SetPen(wx.CYAN_PEN)
  1630                     dc.SetPen(MiterPen(wx.CYAN))
  1590                 else:
  1631                 else:
  1591                     dc.SetPen(wx.GREEN_PEN)
  1632                     dc.SetPen(MiterPen(wx.GREEN))
  1592             elif self.Value == "undefined":
  1633             elif self.Value == "undefined":
  1593                 dc.SetPen(wx.Pen(wx.NamedColour("orange")))
  1634                 dc.SetPen(MiterPen(wx.NamedColour("orange")))
  1594             elif self.Forced:
  1635             elif self.Forced:
  1595                 dc.SetPen(wx.Pen(wx.BLUE))
  1636                 dc.SetPen(MiterPen(wx.BLUE))
  1596             else:
  1637             else:
  1597                 dc.SetPen(wx.BLACK_PEN)
  1638                 dc.SetPen(MiterPen(wx.BLACK))
  1598             dc.SetBrush(wx.WHITE_BRUSH)
  1639             dc.SetBrush(wx.WHITE_BRUSH)
  1599         parent_pos = self.ParentBlock.GetPosition()
  1640         parent_pos = self.ParentBlock.GetPosition()
  1600         
  1641         
  1601         if getattr(dc, "printing", False):
  1642         if getattr(dc, "printing", False):
  1602             name_size = dc.GetTextExtent(self.Name)
  1643             name_size = dc.GetTextExtent(self.Name)
  1607             # If connector is negated, draw a circle
  1648             # If connector is negated, draw a circle
  1608             xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) / 2
  1649             xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) / 2
  1609             ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) / 2
  1650             ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) / 2
  1610             dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
  1651             dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
  1611         else:
  1652         else:
  1612             xstart = parent_pos[0] + self.Pos.x
  1653             xstart = parent_pos[0] + self.Pos.x 
  1613             ystart = parent_pos[1] + self.Pos.y
  1654             ystart = parent_pos[1] + self.Pos.y
  1614             if self.Edge == "rising":
  1655             if self.Edge == "rising":
  1615                 # If connector has a rising edge, draw a right arrow
  1656                 # If connector has a rising edge, draw a right arrow
  1616                 dc.DrawLine(xstart, ystart, xstart - 4, ystart - 4)
  1657                 dc.DrawLine(xstart, ystart, xstart - 4, ystart - 4)
  1617                 dc.DrawLine(xstart, ystart, xstart - 4, ystart + 4)
  1658                 dc.DrawLine(xstart, ystart, xstart - 4, ystart + 4)
  1618             elif self.Edge == "falling":
  1659             elif self.Edge == "falling":
  1619                 # If connector has a falling edge, draw a left arrow
  1660                 # If connector has a falling edge, draw a left arrow
  1620                 dc.DrawLine(xstart, ystart, xstart + 4, ystart - 4)
  1661                 dc.DrawLine(xstart, ystart, xstart + 4, ystart - 4)
  1621                 dc.DrawLine(xstart, ystart, xstart + 4, ystart + 4)
  1662                 dc.DrawLine(xstart, ystart, xstart + 4, ystart + 4)
       
  1663             if self.Direction[0] < 0:
       
  1664                 xstart += 1
       
  1665             if self.Direction[1] < 0:
       
  1666                 ystart += 1
  1622             if self.Selected:
  1667             if self.Selected:
  1623                 xend = xstart + (CONNECTOR_SIZE - 2) * self.Direction[0]
  1668                 xend = xstart + (CONNECTOR_SIZE - 2) * self.Direction[0]
  1624                 yend = ystart + (CONNECTOR_SIZE - 2) * self.Direction[1]
  1669                 yend = ystart + (CONNECTOR_SIZE - 2) * self.Direction[1]
  1625                 dc.DrawLine(xstart + 2 * self.Direction[0], ystart + 2 * self.Direction[1], xend, yend)
  1670                 dc.DrawLine(xstart + 2 * self.Direction[0], ystart + 2 * self.Direction[1], xend, yend)
  1626             else:
  1671             else:
  2697         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2742         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2698             self.EndConnected.RefreshParentBlock()
  2743             self.EndConnected.RefreshParentBlock()
  2699     
  2744     
  2700     # Draws the highlightment of this element if it is highlighted
  2745     # Draws the highlightment of this element if it is highlighted
  2701     def DrawHighlightment(self, dc):
  2746     def DrawHighlightment(self, dc):
  2702         dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
  2747         scalex, scaley = dc.GetUserScale()
       
  2748         dc.SetUserScale(1, 1)
       
  2749         dc.SetPen(MiterPen(HIGHLIGHTCOLOR, (2 * scalex + 5)))
  2703         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2750         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2704         dc.SetLogicalFunction(wx.AND)
  2751         dc.SetLogicalFunction(wx.AND)
  2705         # Draw the start and end points if they are not connected or the mouse is over them
  2752         # Draw the start and end points if they are not connected or the mouse is over them
  2706         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2753         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2707             dc.DrawCircle(self.Points[0].x, self.Points[0].y, POINT_RADIUS + 2)
  2754             dc.DrawCircle(round(self.Points[0].x * scalex), 
       
  2755                           round(self.Points[0].y * scaley), 
       
  2756                           (POINT_RADIUS + 1) * scalex + 2)
  2708         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2757         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2709             dc.DrawCircle(self.Points[-1].x, self.Points[-1].y, POINT_RADIUS + 2)
  2758             dc.DrawCircle(self.Points[-1].x * scalex, self.Points[-1].y * scaley, (POINT_RADIUS + 1) * scalex + 2)
  2710         for i in xrange(len(self.Points) - 1):
  2759         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2711             posx = min(self.Points[i].x, self.Points[i + 1].x) - 2
  2760         if len(self.Points) > 1:
  2712             posy = min(self.Points[i].y, self.Points[i + 1].y) - 2
  2761             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex), 
  2713             width = abs(self.Points[i + 1].x - self.Points[i].x) + 5
  2762                                round((self.Points[0].y - self.Segments[0][1]) * scaley))]
  2714             height = abs(self.Points[i + 1].y - self.Points[i].y) + 5
  2763             points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]])
  2715             dc.DrawRectangle(posx, posy, width, height)
  2764             points.append(wx.Point(round((self.Points[-1].x + self.Segments[-1][0]) * scalex), 
       
  2765                                    round((self.Points[-1].y + self.Segments[-1][1]) * scaley)))
       
  2766         else:
       
  2767             points = []
       
  2768         dc.DrawLines(points)
  2716         dc.SetLogicalFunction(wx.COPY)
  2769         dc.SetLogicalFunction(wx.COPY)
       
  2770         dc.SetUserScale(scalex, scaley)
       
  2771         
  2717         if self.StartConnected is not None:
  2772         if self.StartConnected is not None:
  2718             self.StartConnected.DrawHighlightment(dc)
  2773             self.StartConnected.DrawHighlightment(dc)
  2719             self.StartConnected.Draw(dc)
  2774             self.StartConnected.Draw(dc)
  2720         if self.EndConnected is not None:
  2775         if self.EndConnected is not None:
  2721             self.EndConnected.DrawHighlightment(dc)
  2776             self.EndConnected.DrawHighlightment(dc)
  2723         
  2778         
  2724     # Draws the wire lines and points
  2779     # Draws the wire lines and points
  2725     def Draw(self, dc):
  2780     def Draw(self, dc):
  2726         Graphic_Element.Draw(self, dc)
  2781         Graphic_Element.Draw(self, dc)
  2727         if not self.Valid:
  2782         if not self.Valid:
  2728             dc.SetPen(wx.RED_PEN)
  2783             dc.SetPen(MiterPen(wx.RED))
  2729             dc.SetBrush(wx.RED_BRUSH)
  2784             dc.SetBrush(wx.RED_BRUSH)
  2730         elif isinstance(self.Value, BooleanType) and self.Value:
  2785         elif isinstance(self.Value, BooleanType) and self.Value:
  2731             if self.Forced:
  2786             if self.Forced:
  2732                 dc.SetPen(wx.CYAN_PEN)
  2787                 dc.SetPen(MiterPen(wx.CYAN))
  2733                 dc.SetBrush(wx.CYAN_BRUSH)
  2788                 dc.SetBrush(wx.CYAN_BRUSH)
  2734             else:
  2789             else:
  2735                 dc.SetPen(wx.GREEN_PEN)
  2790                 dc.SetPen(MiterPen(wx.GREEN))
  2736                 dc.SetBrush(wx.GREEN_BRUSH)
  2791                 dc.SetBrush(wx.GREEN_BRUSH)
  2737         elif self.Value == "undefined":
  2792         elif self.Value == "undefined":
  2738             dc.SetPen(wx.Pen(wx.NamedColour("orange")))
  2793             dc.SetPen(MiterPen(wx.NamedColour("orange")))
  2739             dc.SetBrush(wx.Brush(wx.NamedColour("orange")))
  2794             dc.SetBrush(wx.Brush(wx.NamedColour("orange")))
  2740         elif self.Forced:
  2795         elif self.Forced:
  2741             dc.SetPen(wx.Pen(wx.BLUE))
  2796             dc.SetPen(MiterPen(wx.BLUE))
  2742             dc.SetBrush(wx.BLUE_BRUSH)
  2797             dc.SetBrush(wx.BLUE_BRUSH)
  2743         else:
  2798         else:
  2744             dc.SetPen(wx.BLACK_PEN)
  2799             dc.SetPen(MiterPen(wx.BLACK))
  2745             dc.SetBrush(wx.BLACK_BRUSH)
  2800             dc.SetBrush(wx.BLACK_BRUSH)
  2746         # Draw the start and end points if they are not connected or the mouse is over them
  2801         # Draw the start and end points if they are not connected or the mouse is over them
  2747         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2802         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2748             dc.DrawCircle(self.Points[0].x, self.Points[0].y, POINT_RADIUS)
  2803             dc.DrawCircle(self.Points[0].x, self.Points[0].y, POINT_RADIUS)
  2749         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2804         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2750             dc.DrawCircle(self.Points[-1].x, self.Points[-1].y, POINT_RADIUS)
  2805             dc.DrawCircle(self.Points[-1].x, self.Points[-1].y, POINT_RADIUS)
  2751         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2806         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2752         dc.DrawLines(self.Points)
  2807         if len(self.Points) > 1:
  2753         dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
  2808             points = [wx.Point(self.Points[0].x - self.Segments[0][0], self.Points[0].y - self.Segments[0][1])]
       
  2809             points.extend([point for point in self.Points[1:-1]])
       
  2810             points.append(wx.Point(self.Points[-1].x + self.Segments[-1][0], self.Points[-1].y + self.Segments[-1][1]))
       
  2811         else:
       
  2812             points = []
       
  2813         dc.DrawLines(points)
  2754         # Draw the segment selected in red
  2814         # Draw the segment selected in red
  2755         if not getattr(dc, "printing", False) and self.SelectedSegment is not None:
  2815         if not getattr(dc, "printing", False) and self.SelectedSegment is not None:
  2756             dc.SetPen(wx.Pen(wx.BLUE, 3))
  2816             dc.SetPen(MiterPen(wx.BLUE, 3))
  2757             if self.SelectedSegment == len(self.Segments) - 1:
  2817             if self.SelectedSegment == len(self.Segments) - 1:
  2758                 end = 0
  2818                 end = 0
  2759             else:
  2819             else:
  2760                 end = 1
  2820                 end = 1
  2761             dc.DrawLine(self.Points[self.SelectedSegment].x - 1, self.Points[self.SelectedSegment].y,
  2821             dc.DrawLine(self.Points[self.SelectedSegment].x - 1, self.Points[self.SelectedSegment].y,
  2898         # Edit the comment content
  2958         # Edit the comment content
  2899         self.Parent.EditCommentContent(self)
  2959         self.Parent.EditCommentContent(self)
  2900     
  2960     
  2901     # Draws the highlightment of this element if it is highlighted
  2961     # Draws the highlightment of this element if it is highlighted
  2902     def DrawHighlightment(self, dc):
  2962     def DrawHighlightment(self, dc):
  2903         dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
  2963         scalex, scaley = dc.GetUserScale()
       
  2964         dc.SetUserScale(1, 1)
       
  2965         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2904         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2966         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2905         dc.SetLogicalFunction(wx.AND)
  2967         dc.SetLogicalFunction(wx.AND)
  2906         polygon = [wx.Point(self.Pos.x - 2, self.Pos.y - 2), 
  2968         
  2907                    wx.Point(self.Pos.x + self.Size[0] - 8, self.Pos.y - 2),
  2969         left = (self.Pos.x - 1) * scalex - 2
  2908                    wx.Point(self.Pos.x + self.Size[0] + 2, self.Pos.y + 8),
  2970         right = (self.Pos.x + self.Size[0] + 1) * scalex + 2
  2909                    wx.Point(self.Pos.x + self.Size[0] + 2, self.Pos.y + self.Size[1] + 2),
  2971         top = (self.Pos.y - 1) * scaley - 2
  2910                    wx.Point(self.Pos.x - 2, self.Pos.y + self.Size[1] + 2)]
  2972         bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2
       
  2973         angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2
       
  2974         angle_right = (self.Pos.y + 9) * scaley - 2
       
  2975         
       
  2976         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
       
  2977                    wx.Point(right, angle_right), wx.Point(right, bottom),
       
  2978                    wx.Point(left, bottom)]
  2911         dc.DrawPolygon(polygon)
  2979         dc.DrawPolygon(polygon)
       
  2980         
  2912         dc.SetLogicalFunction(wx.COPY)
  2981         dc.SetLogicalFunction(wx.COPY)
       
  2982         dc.SetUserScale(scalex, scaley)
  2913         
  2983         
  2914     # Draws the comment and its content
  2984     # Draws the comment and its content
  2915     def Draw(self, dc):
  2985     def Draw(self, dc):
  2916         Graphic_Element.Draw(self, dc)
  2986         Graphic_Element.Draw(self, dc)
  2917         dc.SetPen(wx.BLACK_PEN)
  2987         dc.SetPen(MiterPen(wx.BLACK))
  2918         dc.SetBrush(wx.WHITE_BRUSH)
  2988         dc.SetBrush(wx.WHITE_BRUSH)
  2919         # Draws the comment shape
  2989         # Draws the comment shape
  2920         polygon = [wx.Point(self.Pos.x, self.Pos.y), 
  2990         polygon = [wx.Point(self.Pos.x, self.Pos.y), 
  2921                    wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y),
  2991                    wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y),
  2922                    wx.Point(self.Pos.x + self.Size[0], self.Pos.y + 10),
  2992                    wx.Point(self.Pos.x + self.Size[0], self.Pos.y + 10),