graphics/GraphicCommons.py
changeset 566 6014ef82a98a
parent 563 3f92a5e18804
child 571 79af7b821233
equal deleted inserted replaced
565:94c11207aa6f 566:6014ef82a98a
    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
  1298         self.OneConnected = onlyone
  1333         self.OneConnected = onlyone
  1299         self.Valid = True
  1334         self.Valid = True
  1300         self.Value = None
  1335         self.Value = None
  1301         self.Forced = False
  1336         self.Forced = False
  1302         self.Selected = False
  1337         self.Selected = False
  1303         self.Errors = {}
  1338         self.Highlights = []
  1304         self.RefreshNameSize()
  1339         self.RefreshNameSize()
  1305     
  1340     
  1306     def Flush(self):
  1341     def Flush(self):
  1307         self.ParentBlock = None
  1342         self.ParentBlock = None
  1308         for wire, handle in self.Wires:
  1343         for wire, handle in self.Wires:
  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