diff -r 85a4bc7dc31e -r 1ccd08cfae0c Viewer.py --- 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"]: