graphics/GraphicCommons.py
changeset 633 3536f4469cde
parent 628 edcd40605fff
child 634 cc3335911c01
equal deleted inserted replaced
632:3ea55a5db68e 633:3536f4469cde
   452         self.currentBox = None
   452         self.currentBox = None
   453         self.Redraw()
   453         self.Redraw()
   454 
   454 
   455     # Method that erase the last box and draw the new box
   455     # Method that erase the last box and draw the new box
   456     def Redraw(self, dc = None):
   456     def Redraw(self, dc = None):
   457         if not dc:
   457         if dc is None:
   458             dc = self.Viewer.GetLogicalDC()
   458             dc = self.Viewer.GetLogicalDC()
   459         scalex, scaley = dc.GetUserScale()
   459         scalex, scaley = dc.GetUserScale()
   460         dc.SetUserScale(1, 1)
   460         dc.SetUserScale(1, 1)
   461         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   461         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   462         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   462         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   471                              self.currentBox.width * scalex, self.currentBox.height * scaley)
   471                              self.currentBox.width * scalex, self.currentBox.height * scaley)
   472         dc.SetUserScale(scalex, scaley)
   472         dc.SetUserScale(scalex, scaley)
   473     
   473     
   474     # Erase last box
   474     # Erase last box
   475     def Erase(self, dc = None):
   475     def Erase(self, dc = None):
   476         if not dc:
   476         if dc is None:
   477             dc = self.Viewer.GetLogicalDC()
   477             dc = self.Viewer.GetLogicalDC()
   478         scalex, scaley = dc.GetUserScale()
   478         scalex, scaley = dc.GetUserScale()
   479         dc.SetUserScale(1, 1)
   479         dc.SetUserScale(1, 1)
   480         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   480         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   481         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   481         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   485                              self.lastBox.width * scalex, self.lastBox.height * scalex)
   485                              self.lastBox.width * scalex, self.lastBox.height * scalex)
   486         dc.SetUserScale(scalex, scaley)
   486         dc.SetUserScale(scalex, scaley)
   487 
   487 
   488     # Draw current box
   488     # Draw current box
   489     def Draw(self, dc = None):
   489     def Draw(self, dc = None):
   490         if not dc:
   490         if dc is None:
   491             dc = self.Viewer.GetLogicalDC()
   491             dc = self.Viewer.GetLogicalDC()
   492         scalex, scaley = dc.GetUserScale()
   492         scalex, scaley = dc.GetUserScale()
   493         dc.SetUserScale(1, 1)
   493         dc.SetUserScale(1, 1)
   494         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   494         dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
   495         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   495         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   521               'helv' : 'Helvetica',
   521               'helv' : 'Helvetica',
   522               'other': 'new century schoolbook',
   522               'other': 'new century schoolbook',
   523               'size' : 12,
   523               'size' : 12,
   524              }
   524              }
   525 
   525 
       
   526 TOOLTIP_MAX_CHARACTERS = 30
       
   527 TOOLTIP_MAX_LINE = 5
       
   528 
   526 class ToolTip(wx.PopupWindow):
   529 class ToolTip(wx.PopupWindow):
   527     
   530     
   528     def __init__(self, parent, tip):
   531     def __init__(self, parent, tip):
   529         wx.PopupWindow.__init__(self, parent)
   532         wx.PopupWindow.__init__(self, parent)
   530         
   533         
   534         self.SetTip(tip)
   537         self.SetTip(tip)
   535         
   538         
   536         self.Bind(wx.EVT_PAINT, self.OnPaint)
   539         self.Bind(wx.EVT_PAINT, self.OnPaint)
   537         
   540         
   538     def SetTip(self, tip):
   541     def SetTip(self, tip):
   539         self.Tip = tip
   542         lines = []
       
   543         for line in tip.splitlines():
       
   544             if line != "":
       
   545                 words = line.split()
       
   546                 new_line = words[0]
       
   547                 for word in words[1:]:
       
   548                     if len(new_line + " " + word) <= TOOLTIP_MAX_CHARACTERS:
       
   549                         new_line += " " + word
       
   550                     else:
       
   551                         lines.append(new_line)
       
   552                         new_line = word
       
   553                 lines.append(new_line)
       
   554             else:
       
   555                 lines.append(line)
       
   556         if len(lines) > TOOLTIP_MAX_LINE:
       
   557             self.Tip = lines[:TOOLTIP_MAX_LINE]
       
   558             if len(self.Tip[-1]) < TOOLTIP_MAX_CHARACTERS - 3:
       
   559                 self.Tip[-1] += "..."
       
   560             else:
       
   561                 self.Tip[-1] = self.Tip[-1][:TOOLTIP_MAX_CHARACTERS - 3] + "..."
       
   562         else:
       
   563             self.Tip = lines
   540         wx.CallAfter(self.RefreshTip)
   564         wx.CallAfter(self.RefreshTip)
   541     
   565     
   542     def MoveToolTip(self, pos):
   566     def MoveToolTip(self, pos):
   543         self.CurrentPosition = pos
   567         self.CurrentPosition = pos
   544         self.SetPosition(pos)
   568         self.SetPosition(pos)
   545     
   569     
   546     def GetTipExtent(self):
   570     def GetTipExtent(self):
   547         max_width = 0
   571         max_width = 0
   548         max_height = 0
   572         max_height = 0
   549         for line in self.Tip.splitlines():
   573         for line in self.Tip:
   550             w, h = self.GetTextExtent(line)
   574             w, h = self.GetTextExtent(line)
   551             max_width = max(max_width, w)
   575             max_width = max(max_width, w)
   552             max_height += h
   576             max_height += h
   553         return max_width, max_height
   577         return max_width, max_height
   554     
   578     
   567         dc.SetFont(wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"]))
   591         dc.SetFont(wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"]))
   568         dc.BeginDrawing()
   592         dc.BeginDrawing()
   569         w, h = self.GetTipExtent()
   593         w, h = self.GetTipExtent()
   570         dc.DrawRectangle(0, 0, w + 4, h + 4)
   594         dc.DrawRectangle(0, 0, w + 4, h + 4)
   571         offset = 0
   595         offset = 0
   572         for line in self.Tip.splitlines():
   596         for line in self.Tip:
   573             dc.DrawText(line, 2, offset + 2)
   597             dc.DrawText(line, 2, offset + 2)
   574             w, h = dc.GetTextExtent(line)
   598             w, h = dc.GetTextExtent(line)
   575             offset += h
   599             offset += h
   576         dc.EndDrawing()
   600         dc.EndDrawing()
   577         event.Skip()
   601         event.Skip()
   638         self.ToolTipPos = None
   662         self.ToolTipPos = None
   639         self.ToolTipTimer = wx.Timer(self.Parent, -1)
   663         self.ToolTipTimer = wx.Timer(self.Parent, -1)
   640         self.Parent.Bind(wx.EVT_TIMER, self.OnToolTipTimer, self.ToolTipTimer)
   664         self.Parent.Bind(wx.EVT_TIMER, self.OnToolTipTimer, self.ToolTipTimer)
   641     
   665     
   642     def __del__(self):
   666     def __del__(self):
   643         self
   667         self.ToolTipTimer.Stop()
   644     
   668     
   645     def GetDefinition(self):
   669     def GetDefinition(self):
   646         return [self.Id], []
   670         return [self.Id], []
   647     
   671     
   648     def TestVisible(self, screen):
   672     def TestVisible(self, screen):
   731     # Returns the Id
   755     # Returns the Id
   732     def GetId(self):
   756     def GetId(self):
   733         return self.Id
   757         return self.Id
   734     
   758     
   735     # Returns if the point given is in the bounding box
   759     # Returns if the point given is in the bounding box
   736     def HitTest(self, pt):
   760     def HitTest(self, pt, connectors=True):
   737         rect = self.BoundingBox
   761         if connectors:
       
   762             rect = self.BoundingBox
       
   763         else:
       
   764             rect = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   738         return rect.InsideXY(pt.x, pt.y)
   765         return rect.InsideXY(pt.x, pt.y)
   739     
   766     
   740     # Returns if the point given is in the bounding box
   767     # Returns if the point given is in the bounding box
   741     def IsInSelection(self, rect):
   768     def IsInSelection(self, rect):
   742         return rect.InsideXY(self.BoundingBox.x, self.BoundingBox.y) and rect.InsideXY(self.BoundingBox.x + self.BoundingBox.width, self.BoundingBox.y + self.BoundingBox.height)
   769         return rect.InsideXY(self.BoundingBox.x, self.BoundingBox.y) and rect.InsideXY(self.BoundingBox.x + self.BoundingBox.width, self.BoundingBox.y + self.BoundingBox.height)
   749     def GetBoundingBox(self):
   776     def GetBoundingBox(self):
   750         return self.BoundingBox
   777         return self.BoundingBox
   751     
   778     
   752     # Returns the RedrawRect
   779     # Returns the RedrawRect
   753     def GetRedrawRect(self, movex = 0, movey = 0):
   780     def GetRedrawRect(self, movex = 0, movey = 0):
   754         dc = self.Parent.GetLogicalDC()
   781         scalex, scaley = self.Parent.GetViewScale()
   755         scalex, scaley = dc.GetUserScale()
       
   756         rect = wx.Rect()
   782         rect = wx.Rect()
   757         rect.x = self.BoundingBox.x - int(HANDLE_SIZE / scalex) - 3 - abs(movex)
   783         rect.x = self.BoundingBox.x - int(HANDLE_SIZE / scalex) - 3 - abs(movex)
   758         rect.y = self.BoundingBox.y - int(HANDLE_SIZE / scaley) - 3 - abs(movey)
   784         rect.y = self.BoundingBox.y - int(HANDLE_SIZE / scaley) - 3 - abs(movey)
   759         rect.width = self.BoundingBox.width + 2 * (int(HANDLE_SIZE / scalex) + abs(movex) + 1) + 4
   785         rect.width = self.BoundingBox.width + 2 * (int(HANDLE_SIZE / scalex) + abs(movex) + 1) + 4
   760         rect.height = self.BoundingBox.height + 2 * (int(HANDLE_SIZE / scaley) + abs(movey) + 1) + 4
   786         rect.height = self.BoundingBox.height + 2 * (int(HANDLE_SIZE / scaley) + abs(movey) + 1) + 4
  1210         for element in self.Elements:
  1236         for element in self.Elements:
  1211             element.Delete()
  1237             element.Delete()
  1212         self.WireExcluded = []
  1238         self.WireExcluded = []
  1213     
  1239     
  1214     # Returns if the point given is in the bounding box of one of the elements of this group
  1240     # Returns if the point given is in the bounding box of one of the elements of this group
  1215     def HitTest(self, pt):
  1241     def HitTest(self, pt, connectors=True):
  1216         result = False
  1242         result = False
  1217         for element in self.Elements:
  1243         for element in self.Elements:
  1218             result |= element.HitTest(pt)
  1244             result |= element.HitTest(pt, connectors)
  1219         return result
  1245         return result
  1220     
  1246     
  1221     # Returns if the element given is in this group
  1247     # Returns if the element given is in this group
  1222     def IsElementIn(self, element):
  1248     def IsElementIn(self, element):
  1223         return element in self.Elements
  1249         return element in self.Elements
  1357     
  1383     
  1358     # Change the variable that indicates if this element is highlighted
  1384     # Change the variable that indicates if this element is highlighted
  1359     def SetHighlighted(self, highlighted):
  1385     def SetHighlighted(self, highlighted):
  1360         for element in self.Elements:
  1386         for element in self.Elements:
  1361             element.SetHighlighted(highlighted)
  1387             element.SetHighlighted(highlighted)
  1362 
  1388     
       
  1389     def HighlightPoint(self, pos):
       
  1390         for element in self.Elements:
       
  1391             if isinstance(element, Wire):
       
  1392                 element.HighlightPoint(pos)
       
  1393     
  1363     # Method called when a LeftDown event have been generated
  1394     # Method called when a LeftDown event have been generated
  1364     def OnLeftDown(self, event, dc, scaling):
  1395     def OnLeftDown(self, event, dc, scaling):
  1365         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1396         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1366         for element in self.Elements:
  1397         for element in self.Elements:
  1367             element.Handle = self.Handle
  1398             element.Handle = self.Handle
  2179             width = MIN_SEGMENT_SIZE
  2210             width = MIN_SEGMENT_SIZE
  2180             height = MIN_SEGMENT_SIZE
  2211             height = MIN_SEGMENT_SIZE
  2181         return width + 1, height + 1
  2212         return width + 1, height + 1
  2182     
  2213     
  2183     # Returns if the point given is on one of the wire segments
  2214     # Returns if the point given is on one of the wire segments
  2184     def HitTest(self, pt):
  2215     def HitTest(self, pt, connectors=True):
  2185         test = False
  2216         test = False
  2186         for i in xrange(len(self.Points) - 1):
  2217         for i in xrange(len(self.Points) - 1):
  2187             rect = wx.Rect(0, 0, 0, 0)
  2218             rect = wx.Rect(0, 0, 0, 0)
  2188             x1, y1 = self.Points[i].x, self.Points[i].y
  2219             if i == 0 and self.StartConnected is not None:
  2189             x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  2220                 x1 = self.Points[i].x - self.Segments[0][0] * CONNECTOR_SIZE
       
  2221                 y1 = self.Points[i].y - self.Segments[0][1] * CONNECTOR_SIZE
       
  2222             else:
       
  2223                 x1, y1 = self.Points[i].x, self.Points[i].y    
       
  2224             if i == len(self.Points) - 2 and self.EndConnected is not None:
       
  2225                 x2 = self.Points[i + 1].x + self.Segments[-1][0] * CONNECTOR_SIZE
       
  2226                 y2 = self.Points[i + 1].y + self.Segments[-1][1] * CONNECTOR_SIZE
       
  2227             else:
       
  2228                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  2190             # Calculate a rectangle around the segment
  2229             # Calculate a rectangle around the segment
  2191             rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  2230             rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  2192                 abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  2231                 abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  2193             test |= rect.InsideXY(pt.x, pt.y) 
  2232             test |= rect.InsideXY(pt.x, pt.y) 
  2194         return test
  2233         return test
  2782                     wx.CallAfter(self.Parent.SetCurrentCursor, 4)
  2821                     wx.CallAfter(self.Parent.SetCurrentCursor, 4)
  2783                 elif result[1] in (EAST, WEST):
  2822                 elif result[1] in (EAST, WEST):
  2784                     wx.CallAfter(self.Parent.SetCurrentCursor, 5)
  2823                     wx.CallAfter(self.Parent.SetCurrentCursor, 5)
  2785                 return 0, 0
  2824                 return 0, 0
  2786             else:
  2825             else:
  2787                 # Test if a point has been handled
       
  2788                 #result = self.TestPoint(pos)
       
  2789                 #if result != None:
       
  2790                 #    if result == 0 and self.StartConnected:
       
  2791                 #        self.OverStart = True
       
  2792                 #    elif result != 0 and self.EndConnected:
       
  2793                 #        self.OverEnd = True
       
  2794                 #else:
       
  2795                 #    self.OverStart = False
       
  2796                 #    self.OverEnd = False
       
  2797                 # Execute the default method for a graphic element
  2826                 # Execute the default method for a graphic element
  2798                 return Graphic_Element.OnMotion(self, event, dc, scaling)
  2827                 return Graphic_Element.OnMotion(self, event, dc, scaling)
  2799         else:
  2828         else:
  2800             # Execute the default method for a graphic element
  2829             # Execute the default method for a graphic element
  2801             return Graphic_Element.OnMotion(self, event, dc, scaling)
  2830             return Graphic_Element.OnMotion(self, event, dc, scaling)
  2865     def RefreshModel(self, move=True):
  2894     def RefreshModel(self, move=True):
  2866         if self.StartConnected and self.StartPoint[1] in [WEST, NORTH]:
  2895         if self.StartConnected and self.StartPoint[1] in [WEST, NORTH]:
  2867             self.StartConnected.RefreshParentBlock()
  2896             self.StartConnected.RefreshParentBlock()
  2868         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2897         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2869             self.EndConnected.RefreshParentBlock()
  2898             self.EndConnected.RefreshParentBlock()
       
  2899     
       
  2900     # Change the variable that indicates if this element is highlighted
       
  2901     def SetHighlighted(self, highlighted):
       
  2902         self.Highlighted = highlighted
       
  2903         if not highlighted:
       
  2904             self.OverStart = False
       
  2905             self.OverEnd = False
       
  2906         self.Refresh()
       
  2907     
       
  2908     def HighlightPoint(self, pos):
       
  2909         refresh = False
       
  2910         start, end = self.OverStart, self.OverEnd
       
  2911         self.OverStart = False
       
  2912         self.OverEnd = False
       
  2913         # Test if a point has been handled
       
  2914         result = self.TestPoint(pos)
       
  2915         if result != None:
       
  2916             if result == 0 and self.StartConnected is not None:
       
  2917                 self.OverStart = True
       
  2918             elif result != 0 and self.EndConnected is not None:
       
  2919                 self.OverEnd = True
       
  2920         if start != self.OverStart or end != self.OverEnd:
       
  2921             self.Refresh()
  2870     
  2922     
  2871     # Draws the highlightment of this element if it is highlighted
  2923     # Draws the highlightment of this element if it is highlighted
  2872     def DrawHighlightment(self, dc):
  2924     def DrawHighlightment(self, dc):
  2873         scalex, scaley = dc.GetUserScale()
  2925         scalex, scaley = dc.GetUserScale()
  2874         dc.SetUserScale(1, 1)
  2926         dc.SetUserScale(1, 1)