Package pallavi :: Package plugins :: Module IncrementalFind
[hide private]
[frames] | no frames]

Source Code for Module pallavi.plugins.IncrementalFind

  1  # Copyright (c) 2007 Dusty Phillips 
  2   
  3  # Permission is hereby granted, free of charge, to any person obtaining a 
  4  # copy of this software and associated documentation files (the "Software"), 
  5  # to deal in the Software without restriction, including without limitation 
  6  # the rights to use, copy, modify, merge, publish, distribute, sublicense, 
  7  # and/or sell copies of the Software, and to permit persons to whom the 
  8  # Software is furnished to do so, subject to the following conditions: 
  9   
 10  # The above copyright notice and this permission notice shall be included in 
 11  # all copies or substantial portions of the Software. 
 12   
 13  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 14  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 15  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 16  # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 17  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 18  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 19  # DEALINGS IN THE SOFTWARE. 
 20   
 21  '''This plugin creates a simple incremental find dialog 
 22  with replace functionality. 
 23   
 24  This plugin allows you to set the following configuration option: 
 25  findOrientation: "HORIZONTAL" or "VERTICAL" 
 26          Set the orientation of the panel, depending on whether you want it docked 
 27          in a horizontal or vertical docking area. The default is HORIZONTAL. 
 28   
 29  This plugin provides the following actions: 
 30  FocusFind 
 31          To show the find window and focus the find textview 
 32           
 33  This plugin invokes the following actions: 
 34  ToggleDockPane 
 35          To show the find window when it is focused 
 36           
 37  This plugin provides the following dock windows: 
 38  Find and Replace 
 39          Dialog that performs incremental find and replace''' 
 40  import wx 
 41  from wx.stc import STC_FIND_MATCHCASE 
 42  from pallavi.EventActionManager import Action 
 43   
 44  findPanel = None 
45 -def setup():
46 if not "findOrientation" in dir(config) or config.findOrientation.upper() == "HORIZONTAL": 47 orientation = wx.HORIZONTAL 48 else: 49 orientation = wx.VERTICAL 50 global findPanel 51 findPanel = FindPanel(orientation) 52 pallavi.AddDockPane(findPanel, "Find and Replace") 53 actions.AddAction(Action("FocusFind", focusFind, "Find and Replace", "Focus Incremental Search box and ensure it is shown"))
54
55 -def focusFind(data=None):
56 if pallavi.dockWindows["Find and Replace"].Parent != pallavi.focusedView or not pallavi.focusedView.dockmanager.GetPane(pallavi.dockWindows["Find and Replace"]).IsShown(): 57 actions.Invoke("ToggleDockPane", "Find and Replace") 58 findPanel.findbox.SetFocus()
59 # Race Condition here; sometimes if the find panel is toggled onto a new window, the setfocus command gets missed. I was waiting for this sort of thing to start happening... 60
61 -class FindPanel(wx.Panel):
62 '''Panel holding find and replace boxes and buttons.'''
63 - def __init__(self, orientation=wx.HORIZONTAL):
64 '''Create the FindPanel. view is a reference to 65 the pallavi.View containing a focusedTextview. Can 66 be specified in a horizontal or vertical orientation depending 67 on where the user would like the panel docked.''' 68 wx.Panel.__init__(self, pallavi.focusedView, wx.ID_ANY) 69 sizer = wx.BoxSizer(orientation) 70 sizer.Add(wx.StaticText(self, wx.ID_ANY, "Find: "), 0, wx.SHAPED | wx.ALIGN_CENTER) 71 self.findbox = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER) 72 sizer.Add(self.findbox, 0, wx.SHAPED | wx.ALIGN_CENTER) 73 sizer.Add(wx.StaticText(self, wx.ID_ANY, "Replace: "), 0, wx.SHAPED | wx.ALIGN_CENTER) 74 self.replacebox = wx.TextCtrl(self, wx.ID_ANY) 75 sizer.Add(self.replacebox, 0, wx.SHAPED | wx.ALIGN_CENTER) 76 findbutton = wx.Button(self, wx.ID_ANY, "Find") 77 sizer.Add(findbutton, 0, wx.SHAPED | wx.ALIGN_CENTER) 78 replacebutton = wx.Button(self, wx.ID_ANY, "Replace") 79 sizer.Add(replacebutton, 0, wx.SHAPED | wx.ALIGN_CENTER) 80 replaceallbutton = wx.Button(self, wx.ID_ANY, "Replace All") 81 sizer.Add(replaceallbutton, 0, wx.SHAPED | wx.ALIGN_CENTER) 82 self.matchcasebox = wx.CheckBox(self, wx.ID_ANY, "Match Case") 83 sizer.Add(self.matchcasebox, 0, wx.SHAPED | wx.ALIGN_CENTER) 84 self.previousbox = wx.CheckBox(self, wx.ID_ANY, "Search Backwards") 85 sizer.Add(self.previousbox, 0, wx.SHAPED | wx.ALIGN_CENTER) 86 87 self.findbox.Bind(wx.EVT_TEXT, self.doFind) 88 self.findbox.Bind(wx.EVT_TEXT_ENTER, self.doFind) 89 self.findbox.Bind(wx.EVT_CHAR, self.escapeFocus) 90 findbutton.Bind(wx.EVT_BUTTON, self.doFind) 91 replacebutton.Bind(wx.EVT_BUTTON, self.doReplace) 92 replaceallbutton.Bind(wx.EVT_BUTTON, self.doReplaceAll) 93 94 sizer.Add((10,10), 2, wx.EXPAND) 95 self.SetSizerAndFit(sizer)
96
97 - def escapeFocus(self, event):
98 if event.KeyCode == 16: 99 self.previousbox.SetValue(not self.previousbox.GetValue()) 100 if event.KeyCode == 27: # Escape 101 pallavi.focusedView.focusedTextView.SetFocus() 102 event.Skip()
103
104 - def doFind(self, event):
105 '''Do a find operation whenever the textbox is updated or 106 the find button is clicked explicitly''' 107 #@TODO This function could do with some serious reorganizing, but I'm sleepy. 108 tv = pallavi.focusedView.focusedTextView 109 if event.EventType == wx.EVT_TEXT.evtType[0]: 110 if self.previousbox.GetValue(): selectionbound = tv.GetSelectionEnd() + 1 111 else: selectionbound = tv.GetSelectionStart() 112 else: 113 if self.previousbox.GetValue(): selectionbound = tv.GetSelectionStart() 114 else: selectionbound = tv.GetSelectionEnd() 115 116 flags = 0 117 if self.matchcasebox.GetValue(): flags = flags | STC_FIND_MATCHCASE 118 longFind = lambda min, max: tv.FindText(min, max, self.findbox.GetValue(), flags) 119 120 if self.previousbox.GetValue(): pos = longFind(selectionbound, 0) 121 else: pos = longFind(selectionbound, tv.GetLength()) 122 if pos == -1: 123 if self.previousbox.GetValue(): pos = longFind(tv.GetLength(), selectionbound) 124 else: pos = longFind(0, selectionbound) 125 actions.Invoke("SetStatusMessage", "Search Hit Bottom, Wrapping") 126 127 if pos != -1: 128 tv.SetSelection(pos, pos + len(self.findbox.GetValue())) 129 else: 130 actions.Invoke("SetStatusMessage", "Search String Not Found")
131
132 - def doReplace(self, event):
133 tv = pallavi.focusedView.focusedTextView 134 sel = tv.GetSelectedText() 135 fs = self.findbox.GetValue() 136 if not self.matchcasebox.GetValue(): 137 sel = sel.lower() 138 fs = fs.lower() 139 if sel == fs: 140 tv.ReplaceSelection(self.replacebox.GetValue()) 141 self.doFind(event)
142
143 - def doReplaceAll(self, event):
144 tv = pallavi.focusedView.focusedTextView 145 tv.SetTargetStart(0) 146 tv.SetTargetEnd(tv.GetLength()) 147 count = 0 148 while tv.SearchInTarget(self.findbox.GetValue()) != -1: 149 tv.ReplaceTarget(self.replacebox.GetValue()) 150 tv.SetTargetStart(0) 151 tv.SetTargetEnd(tv.GetLength()) 152 count += 1 153 actions.Invoke("SetStatusMessage", "%d instances replaced" % count)
154