Viewer.py
changeset 738 1ccd08cfae0c
parent 736 eb6b13d87bfc
child 741 330f578e228d
--- a/Viewer.py	Wed Aug 01 12:44:51 2012 +0200
+++ b/Viewer.py	Fri Aug 10 00:32:05 2012 +0200
@@ -22,6 +22,7 @@
 #License along with this library; if not, write to the Free Software
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+import re
 import math
 import time
 from types import TupleType
@@ -170,6 +171,14 @@
     "actionBlock": actionBlockCreationFunction,
 }
 
+def sort_blocks(block_infos1, block_infos2):
+    x1, y1 = block_infos1[0].GetPosition()
+    x2, y2 = block_infos2[0].GetPosition()
+    if y1 == y2:
+        return cmp(x1, x2)
+    else:
+        return cmp(y1, y2)
+
 #-------------------------------------------------------------------------------
 #                       Graphic elements Viewer base class
 #-------------------------------------------------------------------------------
@@ -557,6 +566,9 @@
         self.current_id = 0
         self.TagName = tagname
         self.Highlights = []
+        self.SearchParams = None
+        self.SearchResults = None
+        self.CurrentFindHighlight = None
         self.InstancePath = instancepath
         self.StartMousePos = None
         self.StartScreenPos = None
@@ -1107,6 +1119,29 @@
             round(maxx / SCROLLBAR_UNIT) + width_incr, round(maxy / SCROLLBAR_UNIT) + height_incr, 
             xstart, ystart, True)
     
+    def EnsureVisible(self, block):
+        xstart, ystart = self.GetViewStart()
+        window_size = self.Editor.GetClientSize()
+        block_bbx = block.GetBoundingBox()
+        
+        screen_minx, screen_miny = xstart * SCROLLBAR_UNIT, ystart * SCROLLBAR_UNIT
+        screen_maxx, screen_maxy = screen_minx + window_size[0], screen_miny + window_size[1]
+        block_minx = int(block_bbx.x * self.ViewScale[0]) 
+        block_miny = int(block_bbx.y * self.ViewScale[1])
+        block_maxx = int(round((block_bbx.x + block_bbx.width) * self.ViewScale[0]))
+        block_maxy = int(round((block_bbx.y + block_bbx.height) * self.ViewScale[1]))
+        
+        xpos, ypos = xstart, ystart
+        if block_minx < screen_minx and block_maxx < screen_maxx:
+            xpos -= (screen_minx - block_minx) / SCROLLBAR_UNIT + 1
+        elif block_maxx > screen_maxx and block_minx > screen_minx:
+            xpos += (block_maxx - screen_maxx) / SCROLLBAR_UNIT + 1
+        if block_miny < screen_miny and block_maxy < screen_maxy:
+            ypos -= (screen_miny - block_miny) / SCROLLBAR_UNIT + 1
+        elif block_maxy > screen_maxy and block_miny > screen_miny:
+            ypos += (block_maxy - screen_maxy) / SCROLLBAR_UNIT + 1
+        self.Scroll(xpos, ypos)
+    
     def SelectInGroup(self, element):
         element.SetSelected(True)
         if self.SelectedElement is None:
@@ -3002,7 +3037,54 @@
                 self.Controler.AddEditedElementActionBlock(self.TagName, block.GetId())
                 self.RefreshActionBlockModel(block)
 
-
+#-------------------------------------------------------------------------------
+#                         Find and Replace functions
+#-------------------------------------------------------------------------------
+
+    def Find(self, direction, search_params):
+        if self.SearchParams != search_params:
+            self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
+            
+            self.SearchParams = search_params
+            criteria = {
+                "raw_pattern": search_params["find_pattern"], 
+                "pattern": re.compile(search_params["find_pattern"]),
+                "case_sensitive": search_params["case_sensitive"],
+                "regular_expression": search_params["regular_expression"],
+                "filter": "all"}
+            
+            self.SearchResults = []
+            blocks = []
+            for infos, start, end, text in self.Controler.SearchInPou(self.TagName, criteria, self.Debug):
+                if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]:
+                    self.SearchResults.append((infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT))
+                else:
+                    block = self.Blocks.get(infos[2])
+                    if block is not None:
+                        blocks.append((block, (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)))
+            blocks.sort(sort_blocks)
+            self.SearchResults.extend([infos for block, infos in blocks])
+        
+        if len(self.SearchResults) > 0:
+            if self.CurrentFindHighlight is not None:
+                old_idx = self.SearchResults.index(self.CurrentFindHighlight)
+                if self.SearchParams["wrap"]:
+                    idx = (old_idx + direction) % len(self.SearchResults)
+                else:
+                    idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1))
+                if idx != old_idx:
+                    self.RemoveHighlight(*self.CurrentFindHighlight)
+                    self.CurrentFindHighlight = self.SearchResults[idx]
+                    self.AddHighlight(*self.CurrentFindHighlight)
+            else:
+                self.CurrentFindHighlight = self.SearchResults[0]
+                self.AddHighlight(*self.CurrentFindHighlight)
+            
+        else:
+            if self.CurrentFindHighlight is not None:
+                self.RemoveHighlight(*self.CurrentFindHighlight)
+            self.CurrentFindHighlight = None
+        
 #-------------------------------------------------------------------------------
 #                        Highlights showing functions
 #-------------------------------------------------------------------------------
@@ -3024,8 +3106,19 @@
         EditorPanel.AddHighlight(self, infos, start, end, highlight_type)
         
         self.Highlights.append((infos, start, end, highlight_type))
-        self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
-        
+        if infos[0] not in ["var_local", "var_input", "var_output", "var_inout"]:
+            block = self.Blocks.get(infos[1])
+            if block is not None:
+                self.EnsureVisible(block)
+            self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
+    
+    def RemoveHighlight(self, infos, start, end, highlight_type):
+        EditorPanel.RemoveHighlight(self, infos, start, end, highlight_type)
+        
+        if (infos, start, end, highlight_type) in self.Highlights:
+            self.Highlights.remove((infos, start, end, highlight_type))
+            self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
+    
     def ShowHighlights(self):
         for infos, start, end, highlight_type in self.Highlights:
             if infos[0] in ["comment", "io_variable", "block", "connector", "coil", "contact", "step", "transition", "jump", "action_block"]: