91 # Contants for defining which drawing mode is selected for app |
91 # Contants for defining which drawing mode is selected for app |
92 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2] |
92 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2] |
93 |
93 |
94 # Color for Highlighting |
94 # Color for Highlighting |
95 HIGHLIGHTCOLOR = wx.CYAN |
95 HIGHLIGHTCOLOR = wx.CYAN |
96 |
96 |
|
97 # Define highlight types |
|
98 ERROR_HIGHLIGHT = (wx.NamedColour("yellow"), wx.RED) |
|
99 SEARCH_RESULT_HIGHLIGHT = (wx.NamedColour("orange"), wx.WHITE) |
|
100 |
|
101 # Define highlight refresh inhibition period in second |
|
102 REFRESH_HIGHLIGHT_PERIOD = 0.1 |
|
103 |
97 HANDLE_CURSORS = { |
104 HANDLE_CURSORS = { |
98 (1, 1) : 2, |
105 (1, 1) : 2, |
99 (3, 3) : 2, |
106 (3, 3) : 2, |
100 (1, 3) : 3, |
107 (1, 3) : 3, |
101 (3, 1) : 3, |
108 (3, 1) : 3, |
529 dc.DrawText(self.Tip, 2, 2) |
536 dc.DrawText(self.Tip, 2, 2) |
530 dc.EndDrawing() |
537 dc.EndDrawing() |
531 event.Skip() |
538 event.Skip() |
532 |
539 |
533 #------------------------------------------------------------------------------- |
540 #------------------------------------------------------------------------------- |
534 # Helper for highlighting error in drawn text |
541 # Helpers for highlighting text |
535 #------------------------------------------------------------------------------- |
542 #------------------------------------------------------------------------------- |
536 |
543 |
537 def HighlightErrorZone(dc, x, y, width, height): |
544 def AddHighlight(highlights, infos): |
|
545 RemoveHighlight(highlights, infos) |
|
546 highlights.append(infos) |
|
547 |
|
548 def RemoveHighlight(highlights, infos): |
|
549 if infos in highlights: |
|
550 highlights.remove(infos) |
|
551 return True |
|
552 return False |
|
553 |
|
554 def ClearHighlight(highlights, highlight_type=None): |
|
555 if highlight_type is not None: |
|
556 return [highlight for highlight in highlights if highlight[2] != highlight_type] |
|
557 return [] |
|
558 |
|
559 def DrawHighlightedText(dc, text, highlights, x, y): |
|
560 current_pen = dc.GetPen() |
538 dc.SetPen(wx.TRANSPARENT_PEN) |
561 dc.SetPen(wx.TRANSPARENT_PEN) |
539 dc.SetLogicalFunction(wx.AND) |
562 for start, end, highlight_type in highlights: |
540 dc.SetBrush(wx.Brush(wx.Colour(0,255,0))) |
563 dc.SetBrush(wx.Brush(highlight_type[0])) |
541 dc.DrawRectangle(x, y, width, height) |
564 offset_width, offset_height = dc.GetTextExtent(text[:start[1]]) |
542 dc.SetLogicalFunction(wx.XOR) |
565 part = text[start[1]:end[1] + 1] |
543 dc.SetBrush(wx.Brush(wx.Colour(255,0,0))) |
566 part_width, part_height = dc.GetTextExtent(part) |
544 dc.DrawRectangle(x, y, width, height) |
567 dc.DrawRectangle(x + offset_width, y, part_width, part_height) |
545 dc.SetLogicalFunction(wx.COPY) |
568 dc.SetTextForeground(highlight_type[1]) |
546 |
569 dc.DrawText(part, x + offset_width, y) |
|
570 dc.SetPen(current_pen) |
|
571 dc.SetTextForeground(wx.BLACK) |
|
572 |
547 #------------------------------------------------------------------------------- |
573 #------------------------------------------------------------------------------- |
548 # Graphic element base class |
574 # Graphic element base class |
549 #------------------------------------------------------------------------------- |
575 #------------------------------------------------------------------------------- |
550 |
576 |
551 """ |
577 """ |
932 movey = self.StartPos.y + self.CurrentDrag.y - self.Pos.y |
958 movey = self.StartPos.y + self.CurrentDrag.y - self.Pos.y |
933 self.Move(movex, movey) |
959 self.Move(movex, movey) |
934 return movex, movey |
960 return movex, movey |
935 return 0, 0 |
961 return 0, 0 |
936 |
962 |
937 def AddError(self, infos, start, end): |
963 # Override this method for defining the method to call for adding an highlight to this element |
|
964 def AddHighlight(self, infos, start, end, highlight_type): |
|
965 pass |
|
966 |
|
967 # Override this method for defining the method to call for removing an highlight from this element |
|
968 def RemoveHighlight(self, infos, start, end, highlight_type): |
|
969 pass |
|
970 |
|
971 # Override this method for defining the method to call for removing all the highlights of one particular type from this element |
|
972 def ClearHighlight(self, highlight_type=None): |
938 pass |
973 pass |
939 |
974 |
940 # Override this method for defining the method to call for refreshing the model of this element |
975 # Override this method for defining the method to call for refreshing the model of this element |
941 def RefreshModel(self, move=True): |
976 def RefreshModel(self, move=True): |
942 pass |
977 pass |
1394 |
1429 |
1395 def RefreshValid(self): |
1430 def RefreshValid(self): |
1396 self.Valid = True |
1431 self.Valid = True |
1397 for wire, handle in self.Wires: |
1432 for wire, handle in self.Wires: |
1398 self.Valid &= wire.GetValid() |
1433 self.Valid &= wire.GetValid() |
1399 |
1434 |
1400 def ReceivingCurrent(self): |
1435 def ReceivingCurrent(self): |
1401 current = False |
1436 current = False |
1402 for wire, handle in self.Wires: |
1437 for wire, handle in self.Wires: |
1403 value = wire.GetValue() |
1438 value = wire.GetValue() |
1404 if current != "undefined" and isinstance(value, BooleanType): |
1439 if current != "undefined" and isinstance(value, BooleanType): |
1605 dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley), |
1640 dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley), |
1606 round(xend * scalex), round(yend * scaley)) |
1641 round(xend * scalex), round(yend * scaley)) |
1607 dc.SetLogicalFunction(wx.COPY) |
1642 dc.SetLogicalFunction(wx.COPY) |
1608 dc.SetUserScale(scalex, scaley) |
1643 dc.SetUserScale(scalex, scaley) |
1609 |
1644 |
1610 def AddError(self, infos, start, end): |
1645 # Adds an highlight to the connector |
1611 if len(infos) == 0: |
1646 def AddHighlight(self, infos, start, end, highlight_type): |
|
1647 if highlight_type == ERROR_HIGHLIGHT: |
1612 for wire, handle in self.Wires: |
1648 for wire, handle in self.Wires: |
1613 wire.SetValid(False) |
1649 wire.SetValid(False) |
|
1650 AddHighlight(self.Highlights, (start, end, highlight_type)) |
|
1651 |
|
1652 # Removes an highlight from the connector |
|
1653 def RemoveHighlight(self, infos, start, end, highlight_type): |
|
1654 error = False |
|
1655 highlights = [] |
|
1656 for highlight in self.Highlights: |
|
1657 if highlight != (start, end, highlight_type): |
|
1658 highlights.append(highlight) |
|
1659 error |= highlight == ERROR_HIGHLIGHT |
|
1660 self.Highlights = highlights |
|
1661 if not error: |
|
1662 for wire, handle in self.Wires: |
|
1663 wire.SetValid(wire.IsConnectedCompatible()) |
|
1664 |
|
1665 # Removes all the highlights of one particular type from the connector |
|
1666 def ClearHighlight(self, highlight_type=None): |
|
1667 error = False |
|
1668 if highlight_type is None: |
|
1669 self.Highlights = [] |
1614 else: |
1670 else: |
1615 self.Errors[infos[0]] = (start, end) |
1671 highlights = [] |
|
1672 for highlight in self.Highlights: |
|
1673 if highlight[2] != highlight_type: |
|
1674 highlights.append(highlight) |
|
1675 error |= highlight == ERROR_HIGHLIGHT |
|
1676 self.Highlights = highlights |
|
1677 if not error: |
|
1678 for wire, handle in self.Wires: |
|
1679 wire.SetValid(wire.IsConnectedCompatible()) |
1616 |
1680 |
1617 # Draws the connector |
1681 # Draws the connector |
1618 def Draw(self, dc): |
1682 def Draw(self, dc): |
1619 if self.Selected: |
1683 if self.Selected: |
1620 dc.SetPen(MiterPen(wx.BLUE, 3)) |
1684 dc.SetPen(MiterPen(wx.BLUE, 3)) |
1621 dc.SetBrush(wx.WHITE_BRUSH) |
1685 dc.SetBrush(wx.WHITE_BRUSH) |
1622 elif len(self.Errors) > 0: |
1686 #elif len(self.Highlights) > 0: |
1623 dc.SetPen(MiterPen(wx.RED)) |
1687 # dc.SetPen(MiterPen(self.Highlights[-1][1])) |
1624 dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0))) |
1688 # dc.SetBrush(wx.Brush(self.Highlights[-1][0])) |
1625 else: |
1689 else: |
1626 if not self.Valid: |
1690 if not self.Valid: |
1627 dc.SetPen(MiterPen(wx.RED)) |
1691 dc.SetPen(MiterPen(wx.RED)) |
1628 elif isinstance(self.Value, BooleanType) and self.Value: |
1692 elif isinstance(self.Value, BooleanType) and self.Value: |
1629 if self.Forced: |
1693 if self.Forced: |
1670 dc.DrawLine(xstart + 2 * self.Direction[0], ystart + 2 * self.Direction[1], xend, yend) |
1734 dc.DrawLine(xstart + 2 * self.Direction[0], ystart + 2 * self.Direction[1], xend, yend) |
1671 else: |
1735 else: |
1672 xend = xstart + CONNECTOR_SIZE * self.Direction[0] |
1736 xend = xstart + CONNECTOR_SIZE * self.Direction[0] |
1673 yend = ystart + CONNECTOR_SIZE * self.Direction[1] |
1737 yend = ystart + CONNECTOR_SIZE * self.Direction[1] |
1674 dc.DrawLine(xstart + self.Direction[0], ystart + self.Direction[1], xend, yend) |
1738 dc.DrawLine(xstart + self.Direction[0], ystart + self.Direction[1], xend, yend) |
1675 if len(self.Errors) > 0: |
|
1676 dc.SetPen(self.Pen) |
|
1677 dc.SetBrush(wx.WHITE_BRUSH) |
|
1678 if self.Direction[0] != 0: |
1739 if self.Direction[0] != 0: |
1679 ytext = parent_pos[1] + self.Pos.y - name_size[1] / 2 |
1740 ytext = parent_pos[1] + self.Pos.y - name_size[1] / 2 |
1680 if self.Direction[0] < 0: |
1741 if self.Direction[0] < 0: |
1681 xtext = parent_pos[0] + self.Pos.x + 5 |
1742 xtext = parent_pos[0] + self.Pos.x + 5 |
1682 else: |
1743 else: |
1687 ytext = parent_pos[1] + self.Pos.y + 5 |
1748 ytext = parent_pos[1] + self.Pos.y + 5 |
1688 else: |
1749 else: |
1689 ytext = parent_pos[1] + self.Pos.y - (name_size[1] + 5) |
1750 ytext = parent_pos[1] + self.Pos.y - (name_size[1] + 5) |
1690 # Draw the text |
1751 # Draw the text |
1691 dc.DrawText(self.Name, xtext, ytext) |
1752 dc.DrawText(self.Name, xtext, ytext) |
1692 |
1753 if not getattr(dc, "printing", False): |
|
1754 DrawHighlightedText(dc, self.Name, self.Highlights, xtext, ytext) |
1693 |
1755 |
1694 #------------------------------------------------------------------------------- |
1756 #------------------------------------------------------------------------------- |
1695 # Common Wire Element |
1757 # Common Wire Element |
1696 #------------------------------------------------------------------------------- |
1758 #------------------------------------------------------------------------------- |
1697 |
1759 |
2773 self.StartConnected.DrawHighlightment(dc) |
2835 self.StartConnected.DrawHighlightment(dc) |
2774 self.StartConnected.Draw(dc) |
2836 self.StartConnected.Draw(dc) |
2775 if self.EndConnected is not None: |
2837 if self.EndConnected is not None: |
2776 self.EndConnected.DrawHighlightment(dc) |
2838 self.EndConnected.DrawHighlightment(dc) |
2777 self.EndConnected.Draw(dc) |
2839 self.EndConnected.Draw(dc) |
2778 |
2840 |
2779 # Draws the wire lines and points |
2841 # Draws the wire lines and points |
2780 def Draw(self, dc): |
2842 def Draw(self, dc): |
2781 Graphic_Element.Draw(self, dc) |
2843 Graphic_Element.Draw(self, dc) |
2782 if not self.Valid: |
2844 if not self.Valid: |
2783 dc.SetPen(MiterPen(wx.RED)) |
2845 dc.SetPen(MiterPen(wx.RED)) |
2846 |
2908 |
2847 #------------------------------------------------------------------------------- |
2909 #------------------------------------------------------------------------------- |
2848 # Graphic comment element |
2910 # Graphic comment element |
2849 #------------------------------------------------------------------------------- |
2911 #------------------------------------------------------------------------------- |
2850 |
2912 |
|
2913 def FilterHighlightsByRow(highlights, row, length): |
|
2914 _highlights = [] |
|
2915 for start, end, highlight_type in highlights: |
|
2916 if start[0] <= row and end[0] >= row: |
|
2917 if start[0] < row: |
|
2918 start = (row, 0) |
|
2919 if end[0] > row: |
|
2920 end = (row, length) |
|
2921 _highlights.append((start, end, highlight_type)) |
|
2922 return _highlights |
|
2923 |
|
2924 def FilterHighlightsByColumn(highlights, start_col, end_col): |
|
2925 _highlights = [] |
|
2926 for start, end, highlight_type in highlights: |
|
2927 if end[1] > start_col and start[1] < end_col: |
|
2928 start = (start[0], max(start[1], start_col) - start_col) |
|
2929 end = (end[0], min(end[1], end_col) - start_col) |
|
2930 _highlights.append((start, end, highlight_type)) |
|
2931 return _highlights |
|
2932 |
2851 """ |
2933 """ |
2852 Class that implements a comment |
2934 Class that implements a comment |
2853 """ |
2935 """ |
2854 |
2936 |
2855 class Comment(Graphic_Element): |
2937 class Comment(Graphic_Element): |
2859 Graphic_Element.__init__(self, parent) |
2941 Graphic_Element.__init__(self, parent) |
2860 self.Id = id |
2942 self.Id = id |
2861 self.Content = content |
2943 self.Content = content |
2862 self.Pos = wx.Point(0, 0) |
2944 self.Pos = wx.Point(0, 0) |
2863 self.Size = wx.Size(0, 0) |
2945 self.Size = wx.Size(0, 0) |
|
2946 self.Highlights = [] |
2864 |
2947 |
2865 # Make a clone of this comment |
2948 # Make a clone of this comment |
2866 def Clone(self, parent, id = None, pos = None): |
2949 def Clone(self, parent, id = None, pos = None): |
2867 comment = Comment(parent, self.Content, id) |
2950 comment = Comment(parent, self.Content, id) |
2868 if pos is not None: |
2951 if pos is not None: |
2955 |
3038 |
2956 # Method called when a LeftDClick event have been generated |
3039 # Method called when a LeftDClick event have been generated |
2957 def OnLeftDClick(self, event, dc, scaling): |
3040 def OnLeftDClick(self, event, dc, scaling): |
2958 # Edit the comment content |
3041 # Edit the comment content |
2959 self.Parent.EditCommentContent(self) |
3042 self.Parent.EditCommentContent(self) |
|
3043 |
|
3044 # Adds an highlight to the comment |
|
3045 def AddHighlight(self, infos, start, end, highlight_type): |
|
3046 if infos[0] == "content": |
|
3047 AddHighlight(self.Highlights, (start, end, highlight_type)) |
|
3048 |
|
3049 # Removes an highlight from the comment |
|
3050 def RemoveHighlight(self, infos, start, end, highlight_type): |
|
3051 RemoveHighlight(self.Highlights, (start, end, highlight_type)) |
|
3052 |
|
3053 # Removes all the highlights of one particular type from the comment |
|
3054 def ClearHighlight(self, highlight_type=None): |
|
3055 self.Highlights = ClearHighlights(self.Highlights, highlight_type) |
2960 |
3056 |
2961 # Draws the highlightment of this element if it is highlighted |
3057 # Draws the highlightment of this element if it is highlighted |
2962 def DrawHighlightment(self, dc): |
3058 def DrawHighlightment(self, dc): |
2963 scalex, scaley = dc.GetUserScale() |
3059 scalex, scaley = dc.GetUserScale() |
2964 dc.SetUserScale(1, 1) |
3060 dc.SetUserScale(1, 1) |
2997 wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y + 10), |
3093 wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y + 10), |
2998 wx.Point(self.Pos.x + self.Size[0], self.Pos.y + 10)] |
3094 wx.Point(self.Pos.x + self.Size[0], self.Pos.y + 10)] |
2999 dc.DrawLines(lines) |
3095 dc.DrawLines(lines) |
3000 # Draws the comment content |
3096 # Draws the comment content |
3001 y = self.Pos.y + 10 |
3097 y = self.Pos.y + 10 |
3002 for line in self.Content.splitlines(): |
3098 for idx, line in enumerate(self.Content.splitlines()): |
3003 first = True |
3099 first = True |
3004 linetext = "" |
3100 linetext = "" |
3005 words = line.split(" ") |
3101 words = line.split(" ") |
|
3102 if not getattr(dc, "printing", False): |
|
3103 highlights = FilterHighlightsByRow(self.Highlights, idx, len(line)) |
|
3104 highlights_offset = 0 |
3006 for i, word in enumerate(words): |
3105 for i, word in enumerate(words): |
3007 if first: |
3106 if first: |
3008 test = word |
3107 text = word |
3009 else: |
3108 else: |
3010 test = linetext + " " + word |
3109 text = linetext + " " + word |
3011 wordwidth, wordheight = dc.GetTextExtent(test) |
3110 wordwidth, wordheight = dc.GetTextExtent(text) |
3012 if y + wordheight > self.Pos.y + self.Size[1] - 10: |
3111 if y + wordheight > self.Pos.y + self.Size[1] - 10: |
3013 break |
3112 break |
3014 if wordwidth < self.Size[0] - 20: |
3113 if wordwidth < self.Size[0] - 20: |
3015 if i < len(words) - 1: |
3114 if i < len(words) - 1: |
3016 linetext = test |
3115 linetext = text |
3017 first = False |
3116 first = False |
3018 else: |
3117 else: |
3019 dc.DrawText(test, self.Pos.x + 10, y) |
3118 dc.DrawText(text, self.Pos.x + 10, y) |
|
3119 if not getattr(dc, "printing", False): |
|
3120 DrawHighlightedText(dc, text, FilterHighlightsByColumn(highlights, highlights_offset, highlights_offset + len(text)), self.Pos.x + 10, y) |
|
3121 highlights_offset += len(text) + 1 |
3020 y += wordheight + 5 |
3122 y += wordheight + 5 |
3021 else: |
3123 else: |
3022 dc.DrawText(linetext, self.Pos.x + 10, y) |
3124 if not first: |
3023 if i == len(words) - 1: |
3125 dc.DrawText(linetext, self.Pos.x + 10, y) |
3024 y += wordheight + 5 |
3126 if not getattr(dc, "printing", False): |
3025 if y + wordheight > self.Pos.y + self.Size[1] - 10: |
3127 DrawHighlightedText(dc, linetext, FilterHighlightsByColumn(highlights, highlights_offset, highlights_offset + len(linetext)), self.Pos.x + 10, y) |
3026 break |
3128 highlights_offset += len(linetext) + 1 |
|
3129 if first or i == len(words) - 1: |
|
3130 if not first: |
|
3131 y += wordheight + 5 |
|
3132 if y + wordheight > self.Pos.y + self.Size[1] - 10: |
|
3133 break |
3027 dc.DrawText(word, self.Pos.x + 10, y) |
3134 dc.DrawText(word, self.Pos.x + 10, y) |
|
3135 if not getattr(dc, "printing", False): |
|
3136 DrawHighlightedText(dc, word, FilterHighlightsByColumn(highlights, highlights_offset, highlights_offset + len(word)), self.Pos.x + 10, y) |
|
3137 highlights_offset += len(word) + 1 |
3028 else: |
3138 else: |
3029 linetext = word |
3139 linetext = word |
3030 y += wordheight + 5 |
3140 y += wordheight + 5 |
3031 if y + wordheight > self.Pos.y + self.Size[1] - 10: |
3141 if y + wordheight > self.Pos.y + self.Size[1] - 10: |
3032 break |
3142 break |