graphics/GraphicCommons.py
changeset 566 6014ef82a98a
parent 563 3f92a5e18804
child 571 79af7b821233
--- a/graphics/GraphicCommons.py	Fri Sep 30 17:16:02 2011 +0200
+++ b/graphics/GraphicCommons.py	Sun Oct 09 19:51:14 2011 +0200
@@ -93,7 +93,14 @@
 
 # Color for Highlighting
 HIGHLIGHTCOLOR = wx.CYAN
-           
+
+# Define highlight types
+ERROR_HIGHLIGHT = (wx.NamedColour("yellow"), wx.RED)
+SEARCH_RESULT_HIGHLIGHT = (wx.NamedColour("orange"), wx.WHITE)
+
+# Define highlight refresh inhibition period in second
+REFRESH_HIGHLIGHT_PERIOD = 0.1
+
 HANDLE_CURSORS = {
     (1, 1) : 2,
     (3, 3) : 2,
@@ -531,19 +538,38 @@
         event.Skip()
 
 #-------------------------------------------------------------------------------
-#                    Helper for highlighting error in drawn text
+#                    Helpers for highlighting text
 #-------------------------------------------------------------------------------
 
-def HighlightErrorZone(dc, x, y, width, height):
+def AddHighlight(highlights, infos):
+    RemoveHighlight(highlights, infos)
+    highlights.append(infos)
+
+def RemoveHighlight(highlights, infos):
+    if infos in highlights:
+        highlights.remove(infos)
+        return True
+    return False
+
+def ClearHighlight(highlights, highlight_type=None):
+    if highlight_type is not None:
+        return [highlight for highlight in highlights if highlight[2] != highlight_type]
+    return []
+
+def DrawHighlightedText(dc, text, highlights, x, y):
+    current_pen = dc.GetPen()
     dc.SetPen(wx.TRANSPARENT_PEN)
-    dc.SetLogicalFunction(wx.AND)
-    dc.SetBrush(wx.Brush(wx.Colour(0,255,0)))
-    dc.DrawRectangle(x, y, width, height)
-    dc.SetLogicalFunction(wx.XOR)
-    dc.SetBrush(wx.Brush(wx.Colour(255,0,0)))
-    dc.DrawRectangle(x, y, width, height)
-    dc.SetLogicalFunction(wx.COPY)
-
+    for start, end, highlight_type in highlights:
+        dc.SetBrush(wx.Brush(highlight_type[0]))
+        offset_width, offset_height = dc.GetTextExtent(text[:start[1]])
+        part = text[start[1]:end[1] + 1]
+        part_width, part_height = dc.GetTextExtent(part)
+        dc.DrawRectangle(x + offset_width, y, part_width, part_height)
+        dc.SetTextForeground(highlight_type[1])
+        dc.DrawText(part, x + offset_width, y)
+    dc.SetPen(current_pen)
+    dc.SetTextForeground(wx.BLACK)
+    
 #-------------------------------------------------------------------------------
 #                           Graphic element base class
 #-------------------------------------------------------------------------------
@@ -934,7 +960,16 @@
             return movex, movey
         return 0, 0
     
-    def AddError(self, infos, start, end):
+    # Override this method for defining the method to call for adding an highlight to this element
+    def AddHighlight(self, infos, start, end, highlight_type):
+        pass
+    
+    # Override this method for defining the method to call for removing an highlight from this element
+    def RemoveHighlight(self, infos, start, end, highlight_type):
+        pass
+    
+    # Override this method for defining the method to call for removing all the highlights of one particular type from this element
+    def ClearHighlight(self, highlight_type=None):
         pass
     
     # Override this method for defining the method to call for refreshing the model of this element
@@ -1300,7 +1335,7 @@
         self.Value = None
         self.Forced = False
         self.Selected = False
-        self.Errors = {}
+        self.Highlights = []
         self.RefreshNameSize()
     
     def Flush(self):
@@ -1396,7 +1431,7 @@
         self.Valid = True
         for wire, handle in self.Wires:
             self.Valid &= wire.GetValid()
-        	
+    
     def ReceivingCurrent(self):
         current = False
         for wire, handle in self.Wires:
@@ -1607,21 +1642,50 @@
         dc.SetLogicalFunction(wx.COPY)
         dc.SetUserScale(scalex, scaley)
     
-    def AddError(self, infos, start, end):
-        if len(infos) == 0:
+    # Adds an highlight to the connector
+    def AddHighlight(self, infos, start, end, highlight_type):
+        if highlight_type == ERROR_HIGHLIGHT:
             for wire, handle in self.Wires:
                 wire.SetValid(False)
+        AddHighlight(self.Highlights, (start, end, highlight_type))
+    
+    # Removes an highlight from the connector
+    def RemoveHighlight(self, infos, start, end, highlight_type):
+        error = False
+        highlights = []
+        for highlight in self.Highlights:
+            if highlight != (start, end, highlight_type):
+                highlights.append(highlight)
+                error |= highlight == ERROR_HIGHLIGHT
+        self.Highlights = highlights
+        if not error:
+            for wire, handle in self.Wires:
+                wire.SetValid(wire.IsConnectedCompatible())
+    
+    # Removes all the highlights of one particular type from the connector
+    def ClearHighlight(self, highlight_type=None):
+        error = False
+        if highlight_type is None:
+            self.Highlights = []
         else:
-            self.Errors[infos[0]] = (start, end)
+            highlights = []
+            for highlight in self.Highlights:
+                if highlight[2] != highlight_type:
+                    highlights.append(highlight)
+                    error |= highlight == ERROR_HIGHLIGHT
+            self.Highlights = highlights
+        if not error:
+            for wire, handle in self.Wires:
+                wire.SetValid(wire.IsConnectedCompatible())
     
     # Draws the connector
     def Draw(self, dc):
         if self.Selected:
             dc.SetPen(MiterPen(wx.BLUE, 3))
             dc.SetBrush(wx.WHITE_BRUSH)
-        elif len(self.Errors) > 0:
-            dc.SetPen(MiterPen(wx.RED))
-            dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
+        #elif len(self.Highlights) > 0:
+        #    dc.SetPen(MiterPen(self.Highlights[-1][1]))
+        #    dc.SetBrush(wx.Brush(self.Highlights[-1][0]))
         else:
             if not self.Valid:
                 dc.SetPen(MiterPen(wx.RED))
@@ -1672,9 +1736,6 @@
                 xend = xstart + CONNECTOR_SIZE * self.Direction[0]
                 yend = ystart + CONNECTOR_SIZE * self.Direction[1]
                 dc.DrawLine(xstart + self.Direction[0], ystart + self.Direction[1], xend, yend)
-        if len(self.Errors) > 0:
-            dc.SetPen(self.Pen)
-            dc.SetBrush(wx.WHITE_BRUSH)
         if self.Direction[0] != 0:
             ytext = parent_pos[1] + self.Pos.y - name_size[1] / 2
             if self.Direction[0] < 0:
@@ -1689,7 +1750,8 @@
                 ytext = parent_pos[1] + self.Pos.y - (name_size[1] + 5)
         # Draw the text
         dc.DrawText(self.Name, xtext, ytext)
-
+        if not getattr(dc, "printing", False):
+            DrawHighlightedText(dc, self.Name, self.Highlights, xtext, ytext)
 
 #-------------------------------------------------------------------------------
 #                           Common Wire Element
@@ -2775,7 +2837,7 @@
         if self.EndConnected is not None:
             self.EndConnected.DrawHighlightment(dc)
             self.EndConnected.Draw(dc)
-        
+    
     # Draws the wire lines and points
     def Draw(self, dc):
         Graphic_Element.Draw(self, dc)
@@ -2848,6 +2910,26 @@
 #                           Graphic comment element
 #-------------------------------------------------------------------------------
 
+def FilterHighlightsByRow(highlights, row, length):
+    _highlights = []
+    for start, end, highlight_type in highlights:
+        if start[0] <= row and end[0] >= row:
+            if start[0] < row:
+                start = (row, 0)
+            if end[0] > row:
+                end = (row, length)
+            _highlights.append((start, end, highlight_type))
+    return _highlights
+
+def FilterHighlightsByColumn(highlights, start_col, end_col):
+    _highlights = []
+    for start, end, highlight_type in highlights:
+        if end[1] > start_col and start[1] < end_col:
+            start = (start[0], max(start[1], start_col) - start_col)
+            end = (end[0], min(end[1], end_col) - start_col)
+            _highlights.append((start, end, highlight_type))
+    return _highlights
+
 """
 Class that implements a comment
 """
@@ -2861,6 +2943,7 @@
         self.Content = content
         self.Pos = wx.Point(0, 0)
         self.Size = wx.Size(0, 0)
+        self.Highlights = []
     
     # Make a clone of this comment
     def Clone(self, parent, id = None, pos = None):
@@ -2958,6 +3041,19 @@
         # Edit the comment content
         self.Parent.EditCommentContent(self)
     
+    # Adds an highlight to the comment
+    def AddHighlight(self, infos, start, end, highlight_type):
+        if infos[0] == "content":
+            AddHighlight(self.Highlights, (start, end, highlight_type))
+    
+    # Removes an highlight from the comment
+    def RemoveHighlight(self, infos, start, end, highlight_type):
+        RemoveHighlight(self.Highlights, (start, end, highlight_type))
+    
+    # Removes all the highlights of one particular type from the comment
+    def ClearHighlight(self, highlight_type=None):
+        self.Highlights = ClearHighlights(self.Highlights, highlight_type)
+    
     # Draws the highlightment of this element if it is highlighted
     def DrawHighlightment(self, dc):
         scalex, scaley = dc.GetUserScale()
@@ -2999,32 +3095,46 @@
         dc.DrawLines(lines)
         # Draws the comment content
         y = self.Pos.y + 10
-        for line in self.Content.splitlines():
+        for idx, line in enumerate(self.Content.splitlines()):
             first = True
             linetext = ""
             words = line.split(" ")
+            if not getattr(dc, "printing", False):
+                highlights = FilterHighlightsByRow(self.Highlights, idx, len(line))
+                highlights_offset = 0
             for i, word in enumerate(words):
                 if first:
-                    test = word
+                    text = word
                 else:
-                    test = linetext + " " + word
-                wordwidth, wordheight = dc.GetTextExtent(test)
+                    text = linetext + " " + word
+                wordwidth, wordheight = dc.GetTextExtent(text)
                 if y + wordheight > self.Pos.y + self.Size[1] - 10:
                     break
                 if wordwidth < self.Size[0] - 20:
                     if i < len(words) - 1:
-                        linetext = test
+                        linetext = text
                         first = False
                     else:
-                        dc.DrawText(test, self.Pos.x + 10, y)
+                        dc.DrawText(text, self.Pos.x + 10, y)
+                        if not getattr(dc, "printing", False):
+                            DrawHighlightedText(dc, text, FilterHighlightsByColumn(highlights, highlights_offset, highlights_offset + len(text)), self.Pos.x + 10, y)
+                            highlights_offset += len(text) + 1
                         y += wordheight + 5
                 else:
-                    dc.DrawText(linetext, self.Pos.x + 10, y)
-                    if i == len(words) - 1:
-                        y += wordheight + 5
-                        if y + wordheight > self.Pos.y + self.Size[1] - 10:
-                            break
+                    if not first:
+                        dc.DrawText(linetext, self.Pos.x + 10, y)
+                        if not getattr(dc, "printing", False):
+                            DrawHighlightedText(dc, linetext, FilterHighlightsByColumn(highlights, highlights_offset, highlights_offset + len(linetext)), self.Pos.x + 10, y)
+                            highlights_offset += len(linetext) + 1
+                    if first or i == len(words) - 1:
+                        if not first:
+                            y += wordheight + 5
+                            if y + wordheight > self.Pos.y + self.Size[1] - 10:
+                                break
                         dc.DrawText(word, self.Pos.x + 10, y)
+                        if not getattr(dc, "printing", False):
+                            DrawHighlightedText(dc, word, FilterHighlightsByColumn(highlights, highlights_offset, highlights_offset + len(word)), self.Pos.x + 10, y)
+                            highlights_offset += len(word) + 1
                     else:
                         linetext = word
                     y += wordheight + 5