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