Browse Source

SD2-567. Implemented search and replace inside the current text selection.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1261 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 20 years ago
parent
commit
f93aa9c02d
  1. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 24
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Commands/SearchMainMenuCommands.cs
  3. 32
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/Search.cs
  4. 48
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceInFilesManager.cs
  5. 96
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceManager.cs
  6. 22
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceUtilities.cs
  7. 27
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/BruteForceSearchStrategy.cs
  8. 5
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/ISearchStrategy.cs
  9. 25
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/RegExSearchStrategy.cs
  10. 27
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/WildcardSearchStrategy.cs
  11. 49
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/TextSelection.cs
  12. 9
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplaceDialog.cs
  13. 262
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -752,6 +752,7 @@ @@ -752,6 +752,7 @@
<Compile Include="Src\Util\LineReceivedEventArgs.cs" />
<Compile Include="Src\Util\OutputReader.cs" />
<Compile Include="Src\Util\ProcessRunner.cs" />
<Compile Include="Src\TextEditor\SearchAndReplace\Engine\TextSelection.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\DockPanel_Src\WinFormsUI\WinFormsUI.csproj">

24
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Commands/SearchMainMenuCommands.cs

@ -32,14 +32,10 @@ namespace SearchAndReplace @@ -32,14 +32,10 @@ namespace SearchAndReplace
public static void SetSearchPattern()
{
// Get Highlighted value and set it to FindDialog.searchPattern
IWorkbenchWindow window = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow;
if (window != null && (window.ViewContent is ITextEditorControlProvider)) {
TextEditorControl textarea = ((ITextEditorControlProvider)window.ViewContent).TextEditorControl;
string selectedText = textarea.ActiveTextAreaControl.TextArea.SelectionManager.SelectedText;
if (selectedText != null && selectedText.Length > 0) {
SearchOptions.CurrentFindPattern = selectedText;
}
TextEditorControl textArea = SearchReplaceUtilities.GetActiveTextEditor();
string selectedText = textArea.ActiveTextAreaControl.TextArea.SelectionManager.SelectedText;
if (selectedText != null && selectedText.Length > 0 && !IsMultipleLines(selectedText)) {
SearchOptions.CurrentFindPattern = selectedText;
}
}
@ -48,13 +44,23 @@ namespace SearchAndReplace @@ -48,13 +44,23 @@ namespace SearchAndReplace
SetSearchPattern();
SearchAndReplaceDialog.ShowSingleInstance(SearchAndReplaceMode.Search);
}
static bool IsMultipleLines(string text)
{
return text.IndexOf('\n') != -1;
}
}
public class FindNext : AbstractMenuCommand
{
public override void Run()
{
SearchReplaceManager.FindNext();
if (SearchOptions.CurrentFindPattern.Length > 0) {
SearchReplaceManager.FindNext();
} else {
Find find = new Find();
find.Run();
}
}
}

32
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/Search.cs

@ -119,5 +119,37 @@ namespace SearchAndReplace @@ -119,5 +119,37 @@ namespace SearchAndReplace
}
return null;
}
public SearchResult FindNext(int offset, int length)
{
if (info != null && textIterator != null && documentIterator.CurrentFileName != null) {
if (info.FileName != documentIterator.CurrentFileName) { // create new iterator, if document changed
info = documentIterator.Current;
textIterator = textIteratorBuilder.BuildTextIterator(info);
} else { // old document -> initialize iterator position to caret pos
textIterator.Position = info.CurrentOffset;
}
SearchResult result = CreateNamedSearchResult(searchStrategy.FindNext(textIterator, offset, length));
if (result != null) {
info.CurrentOffset = textIterator.Position;
return result;
}
}
// not found or first start -> move forward to the next document
if (documentIterator.MoveForward()) {
info = documentIterator.Current;
// document is valid for searching -> set iterator & fileName
if (info != null && info.TextBuffer != null && info.EndOffset >= 0 && info.EndOffset < info.TextBuffer.Length) {
textIterator = textIteratorBuilder.BuildTextIterator(info);
} else {
textIterator = null;
}
return FindNext(offset, length);
}
return null;
}
}
}

48
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceInFilesManager.cs

@ -100,6 +100,37 @@ namespace SearchAndReplace @@ -100,6 +100,37 @@ namespace SearchAndReplace
FinishSearchInFiles(results);
}
public static void ReplaceAll(int offset, int length)
{
if (!InitializeSearchInFiles()) {
return;
}
List<SearchResult> results = new List<SearchResult>();
while (true) {
SearchResult result = find.FindNext(offset, length);
if (result == null) {
break;
}
string replacement = result.TransformReplacePattern(SearchOptions.ReplacePattern);
find.Replace(result.Offset,
result.Length,
replacement);
length -= result.Length - replacement.Length;
// HACK - Move the cursor to the correct offset - the caret gets
// moved before the replace range if we replace a string with a
// single character. The ProvidedDocInfo.Replace method assumes that
// the current offset is at the end of the found text which it is not.
find.CurrentDocumentInformation.CurrentOffset = result.Offset + replacement.Length - 1;
results.Add(result);
}
FinishSearchInFiles(results);
}
public static void FindAll()
{
if (!InitializeSearchInFiles()) {
@ -116,6 +147,23 @@ namespace SearchAndReplace @@ -116,6 +147,23 @@ namespace SearchAndReplace
}
FinishSearchInFiles(results);
}
public static void FindAll(int offset, int length)
{
if (!InitializeSearchInFiles()) {
return;
}
List<SearchResult> results = new List<SearchResult>();
while (true) {
SearchResult result = find.FindNext(offset, length);
if (result == null) {
break;
}
results.Add(result);
}
FinishSearchInFiles(results);
}
static void OnSearchAllFinished(SearchAllFinishedEventArgs e)
{

96
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceManager.cs

@ -63,6 +63,42 @@ namespace SearchAndReplace @@ -63,6 +63,42 @@ namespace SearchAndReplace
FindNext();
}
static TextSelection textSelection;
public static void ReplaceFirstInSelection(int offset, int length)
{
SetSearchOptions();
FindFirstInSelection(offset, length);
}
public static bool ReplaceNextInSelection()
{
if (lastResult != null && WorkbenchSingleton.Workbench.ActiveWorkbenchWindow != null) {
ITextEditorControlProvider provider = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ViewContent as ITextEditorControlProvider;
if (provider != null) {
TextEditorControl textarea = provider.TextEditorControl;
SelectionManager selectionManager = textarea.ActiveTextAreaControl.TextArea.SelectionManager;
if (selectionManager.SelectionCollection.Count == 1
&& selectionManager.SelectionCollection[0].Offset == lastResult.Offset
&& selectionManager.SelectionCollection[0].Length == lastResult.Length
&& lastResult.FileName == textarea.FileName)
{
string replacePattern = lastResult.TransformReplacePattern(SearchOptions.ReplacePattern);
textarea.BeginUpdate();
selectionManager.ClearSelection();
textarea.Document.Replace(lastResult.Offset, lastResult.Length, replacePattern);
textarea.ActiveTextAreaControl.Caret.Position = textarea.Document.OffsetToPosition(lastResult.Offset + replacePattern.Length);
textarea.EndUpdate();
textSelection.Length -= lastResult.Length - replacePattern.Length;
}
}
}
return FindNextInSelection();
}
public static void MarkAll()
{
SetSearchOptions();
@ -185,15 +221,65 @@ namespace SearchAndReplace @@ -185,15 +221,65 @@ namespace SearchAndReplace
int startPos = Math.Min(textArea.Document.TextLength, Math.Max(0, result.Offset));
int endPos = Math.Min(textArea.Document.TextLength, startPos + result.Length);
textArea.ActiveTextAreaControl.Caret.Position = textArea.Document.OffsetToPosition(endPos);
textArea.ActiveTextAreaControl.TextArea.SelectionManager.ClearSelection();
textArea.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, textArea.Document.OffsetToPosition(startPos),
textArea.Document.OffsetToPosition(endPos)));
textArea.Refresh();
SearchReplaceUtilities.SelectText(textArea, startPos, endPos);
lastResult = result;
}
}
}
}
static bool foundAtLeastOneItem = false;
public static void FindFirstInSelection(int offset, int length)
{
foundAtLeastOneItem = false;
textSelection = null;
SetSearchOptions();
if (find == null ||
SearchOptions.FindPattern == null ||
SearchOptions.FindPattern.Length == 0) {
return;
}
if (!find.SearchStrategy.CompilePattern()) {
find.Reset();
lastResult = null;
return;
}
textSelection = new TextSelection(offset, length);
FindNextInSelection();
}
public static bool FindNextInSelection()
{
TextEditorControl textArea = null;
while (textArea == null) {
SearchResult result = find.FindNext(textSelection.Offset, textSelection.Length);
if (result == null) {
if (!foundAtLeastOneItem) {
ShowNotFoundMessage();
}
find.Reset();
lastResult = null;
foundAtLeastOneItem = false;
return false;
} else {
textArea = OpenTextArea(result.FileName);
if (textArea != null) {
foundAtLeastOneItem = true;
if (lastResult != null && lastResult.FileName == result.FileName &&
textArea.ActiveTextAreaControl.Caret.Offset != lastResult.Offset + lastResult.Length) {
}
int startPos = Math.Min(textArea.Document.TextLength, Math.Max(0, result.Offset));
int endPos = Math.Min(textArea.Document.TextLength, startPos + result.Length);
SearchReplaceUtilities.SelectText(textArea, startPos, endPos);
lastResult = result;
}
}
}
return true;
}
static void ShowNotFoundMessage()

22
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceUtilities.cs

@ -26,6 +26,15 @@ namespace SearchAndReplace @@ -26,6 +26,15 @@ namespace SearchAndReplace
}
}
public static TextEditorControl GetActiveTextEditor()
{
IWorkbenchWindow window = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow;
if (window != null && (window.ViewContent is ITextEditorControlProvider)) {
return ((ITextEditorControlProvider)window.ViewContent).TextEditorControl;
}
return null;
}
public static bool IsWholeWordAt(ITextBufferStrategy document, int offset, int length)
{
return (offset - 1 < 0 || Char.IsWhiteSpace(document.GetCharAt(offset - 1))) &&
@ -95,5 +104,18 @@ namespace SearchAndReplace @@ -95,5 +104,18 @@ namespace SearchAndReplace
}
return true;
}
public static void SelectText(TextEditorControl textArea, int offset, int endOffset)
{
int textLength = textArea.ActiveTextAreaControl.Document.TextLength;
if (textLength < endOffset) {
endOffset = textLength - 1;
}
textArea.ActiveTextAreaControl.Caret.Position = textArea.Document.OffsetToPosition(endOffset);
textArea.ActiveTextAreaControl.TextArea.SelectionManager.ClearSelection();
textArea.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, textArea.Document.OffsetToPosition(offset),
textArea.Document.OffsetToPosition(endOffset)));
textArea.Refresh();
}
}
}

27
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/BruteForceSearchStrategy.cs

@ -58,6 +58,22 @@ namespace SearchAndReplace @@ -58,6 +58,22 @@ namespace SearchAndReplace
return -1;
}
int InternalFindNext(ITextIterator textIterator, int offset, int length)
{
while (textIterator.MoveAhead(1) && TextSelection.IsInsideRange(textIterator.Position, offset, length)) {
if (SearchOptions.MatchCase ? MatchCaseSensitive(textIterator.TextBuffer, textIterator.Position, searchPattern) : MatchCaseInsensitive(textIterator.TextBuffer, textIterator.Position, searchPattern)) {
if (!SearchOptions.MatchWholeWord || IsWholeWordAt(textIterator.TextBuffer, textIterator.Position, searchPattern.Length)) {
if (TextSelection.IsInsideRange(textIterator.Position + searchPattern.Length - 1, offset, length)) {
return textIterator.Position;
} else {
return -1;
}
}
}
}
return -1;
}
public bool CompilePattern()
{
searchPattern = SearchOptions.MatchCase ? SearchOptions.FindPattern : SearchOptions.FindPattern.ToUpper();
@ -67,6 +83,17 @@ namespace SearchAndReplace @@ -67,6 +83,17 @@ namespace SearchAndReplace
public SearchResult FindNext(ITextIterator textIterator)
{
int offset = InternalFindNext(textIterator);
return GetSearchResult(offset);
}
public SearchResult FindNext(ITextIterator textIterator, int offset, int length)
{
int foundOffset = InternalFindNext(textIterator, offset, length);
return GetSearchResult(foundOffset);
}
SearchResult GetSearchResult(int offset)
{
return offset >= 0 ? new SearchResult(offset, searchPattern.Length) : null;
}
}

5
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/ISearchStrategy.cs

@ -31,5 +31,10 @@ namespace SearchAndReplace @@ -31,5 +31,10 @@ namespace SearchAndReplace
/// compiled pattern in the text using the textIterator and options.
/// </remarks>
SearchResult FindNext(ITextIterator textIterator);
/// <summary>
/// Find only in the specified range.
/// </summary>
SearchResult FindNext(ITextIterator textIterator, int offset, int length);
}
}

25
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/RegExSearchStrategy.cs

@ -53,6 +53,31 @@ namespace SearchAndReplace @@ -53,6 +53,31 @@ namespace SearchAndReplace
return null;
}
public SearchResult FindNext(ITextIterator textIterator, int offset, int length)
{
string document = textIterator.TextBuffer.GetText(0, textIterator.TextBuffer.Length);
while (textIterator.MoveAhead(1) && TextSelection.IsInsideRange(textIterator.Position, offset, length)) {
Match m = regex.Match(document, textIterator.Position);
if (m == null || m.Index <= 0 || m.Length <= 0) {
} else {
int delta = m.Index - textIterator.Position;
if (delta <= 0 || textIterator.MoveAhead(delta)) {
if (TextSelection.IsInsideRange(m.Index + m.Length - 1, offset, length)) {
return new RegexSearchResult(m);
} else {
return null;
}
} else {
return null;
}
}
}
return null;
}
private class RegexSearchResult : SearchResult
{
Match m;

27
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/WildcardSearchStrategy.cs

@ -144,6 +144,22 @@ namespace SearchAndReplace @@ -144,6 +144,22 @@ namespace SearchAndReplace
return -1;
}
int InternalFindNext(ITextIterator textIterator, int offset, int length)
{
while (textIterator.MoveAhead(1) && TextSelection.IsInsideRange(textIterator.Position, offset, length)) {
if (Match(textIterator.TextBuffer, textIterator.Position, !SearchOptions.MatchCase, 0)) {
if (!SearchOptions.MatchWholeWord || SearchReplaceUtilities.IsWholeWordAt(textIterator.TextBuffer, textIterator.Position, curMatchEndOffset - textIterator.Position)) {
if (TextSelection.IsInsideRange(curMatchEndOffset - 1, offset, length)) {
return textIterator.Position;
} else {
return -1;
}
}
}
}
return -1;
}
public bool CompilePattern()
{
CompilePattern(SearchOptions.FindPattern, !SearchOptions.MatchCase);
@ -153,6 +169,17 @@ namespace SearchAndReplace @@ -153,6 +169,17 @@ namespace SearchAndReplace
public SearchResult FindNext(ITextIterator textIterator)
{
int offset = InternalFindNext(textIterator);
return GetSearchResult(offset);
}
public SearchResult FindNext(ITextIterator textIterator, int offset, int length)
{
int foundOffset = InternalFindNext(textIterator, offset, length);
return GetSearchResult(foundOffset);
}
SearchResult GetSearchResult(int offset)
{
return offset >= 0 ? new SearchResult(offset, curMatchEndOffset - offset) : null;
}
}

49
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/TextSelection.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
namespace SearchAndReplace
{
public class TextSelection
{
int offset;
int length;
public TextSelection(int offset, int length)
{
this.offset = offset;
this.length = length;
}
public int Length {
get {
return length;
}
set {
length = value;
}
}
public int Offset {
get {
return offset;
}
set {
offset = value;
}
}
/// <summary>
/// Checks whether a position is in a specified range.
/// </summary>
public static bool IsInsideRange(int position, int offset, int length)
{
return position >= offset && position < offset + length;
}
}
}

9
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplaceDialog.cs

@ -11,6 +11,7 @@ using System.Windows.Forms; @@ -11,6 +11,7 @@ using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.TextEditor.Document;
namespace SearchAndReplace
{
@ -21,8 +22,8 @@ namespace SearchAndReplace @@ -21,8 +22,8 @@ namespace SearchAndReplace
public class SearchAndReplaceDialog : Form
{
public static string SearchPattern = "";
public static string ReplacePattern = "";
public static string SearchPattern = String.Empty;
public static string ReplacePattern = String.Empty;
static SearchAndReplaceDialog Instance;
@ -45,7 +46,7 @@ namespace SearchAndReplace @@ -45,7 +46,7 @@ namespace SearchAndReplace
ToolStripButton replaceButton = new ToolStripButton();
SearchAndReplacePanel searchAndReplacePanel;
public SearchAndReplaceDialog(SearchAndReplaceMode searchAndReplaceMode)
{
this.Owner = WorkbenchSingleton.MainForm;
@ -96,7 +97,6 @@ namespace SearchAndReplace @@ -96,7 +97,6 @@ namespace SearchAndReplace
}
}
void SearchButtonClick(object sender, EventArgs e)
{
if (!searchButton.Checked) {
@ -126,6 +126,5 @@ namespace SearchAndReplace @@ -126,6 +126,5 @@ namespace SearchAndReplace
this.ClientSize = new Size(430, 385);
}
}
}
}

262
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Gui/SearchAndReplacePanel.cs

@ -24,6 +24,10 @@ namespace SearchAndReplace @@ -24,6 +24,10 @@ namespace SearchAndReplace
public class SearchAndReplacePanel : BaseSharpDevelopUserControl
{
SearchAndReplaceMode searchAndReplaceMode;
ISelection selection;
TextEditorControl textEditor;
bool ignoreSelectionChanges;
bool findFirst;
public SearchAndReplaceMode SearchAndReplaceMode {
get {
@ -36,12 +40,12 @@ namespace SearchAndReplace @@ -36,12 +40,12 @@ namespace SearchAndReplace
switch (searchAndReplaceMode) {
case SearchAndReplaceMode.Search:
SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.FindPanel.xfrm"));
Get<Button>("findAll").Click += new EventHandler(FindAllButtonClicked);
Get<Button>("findAll").Click += FindAllButtonClicked;
break;
case SearchAndReplaceMode.Replace:
SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.ReplacePanel.xfrm"));
Get<Button>("replace").Click += new EventHandler(ReplaceButtonClicked);
Get<Button>("replaceAll").Click += new EventHandler(ReplaceAllButtonClicked);
Get<Button>("replace").Click += ReplaceButtonClicked;
Get<Button>("replaceAll").Click += ReplaceAllButtonClicked;
break;
}
@ -57,6 +61,22 @@ namespace SearchAndReplace @@ -57,6 +61,22 @@ namespace SearchAndReplace
{
}
protected override void Dispose(bool disposing)
{
RemoveSelectionChangedHandler();
RemoveActiveWindowChangedHandler();
base.Dispose(disposing);
}
public DocumentIteratorType DocumentIteratorType {
get {
return (DocumentIteratorType)(Get<ComboBox>("lookIn").SelectedIndex);
}
set {
Get<ComboBox>("lookIn").SelectedIndex = (int)value;
}
}
void LookInBrowseButtonClicked(object sender, EventArgs e)
{
FolderDialog dlg = new FolderDialog();
@ -69,25 +89,49 @@ namespace SearchAndReplace @@ -69,25 +89,49 @@ namespace SearchAndReplace
void FindNextButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
SearchReplaceManager.FindNext();
if (IsSelectionSearch) {
if (IsTextSelected(selection)) {
FindNextInSelection();
}
} else {
SearchReplaceManager.FindNext();
}
}
void FindAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
SearchReplaceInFilesManager.FindAll();
if (IsSelectionSearch) {
if (IsTextSelected(selection)) {
FindAllInSelection();
}
} else {
SearchReplaceInFilesManager.FindAll();
}
}
void ReplaceAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
SearchReplaceManager.ReplaceAll();
if (IsSelectionSearch) {
if (IsTextSelected(selection)) {
ReplaceAllInSelection();
}
} else {
SearchReplaceManager.ReplaceAll();
}
}
void ReplaceButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
SearchReplaceManager.Replace();
if (IsSelectionSearch) {
if (IsTextSelected(selection)) {
ReplaceInSelection();
}
} else {
SearchReplaceManager.Replace();
}
}
void WritebackOptions()
@ -149,7 +193,12 @@ namespace SearchAndReplace @@ -149,7 +193,12 @@ namespace SearchAndReplace
}
Get<ComboBox>("lookIn").Items.Add(SearchOptions.LookIn);
Get<ComboBox>("lookIn").SelectedIndexChanged += new EventHandler(LookInSelectedIndexChanged);
Get<ComboBox>("lookIn").SelectedIndex = (int)SearchOptions.DocumentIteratorType;
if (IsMultipleLineSelection(GetCurrentTextSelection())) {
DocumentIteratorType = DocumentIteratorType.CurrentSelection;
} else {
DocumentIteratorType = SearchOptions.DocumentIteratorType;
}
Get<ComboBox>("fileTypes").Text = SearchOptions.LookInFiletypes;
Get<CheckBox>("matchCase").Checked = SearchOptions.MatchCase;
@ -186,6 +235,203 @@ namespace SearchAndReplace @@ -186,6 +235,203 @@ namespace SearchAndReplace
Get<ComboBox>("fileTypes").Enabled = false;
Get<Label>("lookAtTypes").Enabled = false;
}
if (IsSelectionSearch) {
InitSelectionSearch();
} else {
RemoveSelectionSearchHandlers();
}
}
bool IsSelectionSearch {
get {
return DocumentIteratorType == DocumentIteratorType.CurrentSelection;
}
}
/// <summary>
/// Checks whether the selection spans two or more lines.
/// </summary>
/// <remarks>Maybe the ISelection interface should have an
/// IsMultipleLine method?</remarks>
static bool IsMultipleLineSelection(ISelection selection)
{
if (IsTextSelected(selection)) {
return selection.SelectedText.IndexOf('\n') != -1;
}
return false;
}
static bool IsTextSelected(ISelection selection)
{
if (selection != null) {
return !selection.IsEmpty;
}
return false;
}
void FindNextInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
if (findFirst) {
SetCaretPosition(textEditor.ActiveTextAreaControl.TextArea, startOffset);
}
try {
ignoreSelectionChanges = true;
if (findFirst) {
findFirst = false;
SearchReplaceManager.FindFirstInSelection(startOffset, endOffset - startOffset);
} else {
findFirst = !SearchReplaceManager.FindNextInSelection();
if (findFirst) {
SearchReplaceUtilities.SelectText(textEditor, startOffset, endOffset);
}
}
} finally {
ignoreSelectionChanges = false;
}
}
/// <summary>
/// Returns the first ISelection object from the currently active text editor
/// </summary>
static ISelection GetCurrentTextSelection()
{
TextEditorControl textArea = SearchReplaceUtilities.GetActiveTextEditor();
if (textArea != null) {
SelectionManager selectionManager = textArea.ActiveTextAreaControl.SelectionManager;
if (selectionManager.HasSomethingSelected) {
return selectionManager.SelectionCollection[0];
}
}
return null;
}
void WorkbenchWindowChanged(object source, EventArgs e)
{
TextEditorControl activeTextEditorControl = SearchReplaceUtilities.GetActiveTextEditor();
if (activeTextEditorControl != this.textEditor) {
AddSelectionChangedHandler(activeTextEditorControl);
TextSelectionChanged(source, e);
}
}
void AddSelectionChangedHandler(TextEditorControl textEditor)
{
RemoveSelectionChangedHandler();
this.textEditor = textEditor;
if (textEditor != null) {
this.textEditor.ActiveTextAreaControl.SelectionManager.SelectionChanged += TextSelectionChanged;
}
}
void RemoveSelectionChangedHandler()
{
if (textEditor != null) {
textEditor.ActiveTextAreaControl.SelectionManager.SelectionChanged -= TextSelectionChanged;
}
}
void RemoveActiveWindowChangedHandler()
{
WorkbenchSingleton.Workbench.ActiveWorkbenchWindowChanged -= WorkbenchWindowChanged;
}
/// <summary>
/// When the selected text is changed make sure the 'Current Selection'
/// option is not selected if no text is selected.
/// </summary>
/// <remarks>The text selection can change either when the user
/// selects different text in the editor or the active window is
/// changed.</remarks>
void TextSelectionChanged(object source, EventArgs e)
{
if (!ignoreSelectionChanges) {
LoggingService.Debug("TextSelectionChanged.");
selection = GetCurrentTextSelection();
findFirst = true;
}
}
void SetCaretPosition(TextArea textArea, int offset)
{
textArea.Caret.Position = textArea.Document.OffsetToPosition(offset);
}
void InitSelectionSearch()
{
findFirst = true;
selection = GetCurrentTextSelection();
AddSelectionChangedHandler(SearchReplaceUtilities.GetActiveTextEditor());
WorkbenchSingleton.Workbench.ActiveWorkbenchWindowChanged += WorkbenchWindowChanged;
}
void RemoveSelectionSearchHandlers()
{
RemoveSelectionChangedHandler();
RemoveActiveWindowChangedHandler();
}
void FindAllInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
SearchReplaceUtilities.SelectText(textEditor, startOffset, endOffset);
SetCaretPosition(textEditor.ActiveTextAreaControl.TextArea, startOffset);
try {
ignoreSelectionChanges = true;
SearchReplaceInFilesManager.FindAll(startOffset, endOffset - startOffset);
SearchReplaceUtilities.SelectText(textEditor, startOffset, endOffset);
} finally {
ignoreSelectionChanges = false;
}
}
void ReplaceAllInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
SearchReplaceUtilities.SelectText(textEditor, startOffset, endOffset);
SetCaretPosition(textEditor.ActiveTextAreaControl.TextArea, startOffset);
try {
ignoreSelectionChanges = true;
SearchReplaceInFilesManager.ReplaceAll(startOffset, endOffset - startOffset);
SearchReplaceUtilities.SelectText(textEditor, startOffset, endOffset);
} finally {
ignoreSelectionChanges = false;
}
}
void ReplaceInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
if (findFirst) {
SetCaretPosition(textEditor.ActiveTextAreaControl.TextArea, startOffset);
}
try {
ignoreSelectionChanges = true;
if (findFirst) {
findFirst = false;
SearchReplaceManager.ReplaceFirstInSelection(startOffset, endOffset - startOffset);
} else {
findFirst = !SearchReplaceManager.ReplaceNextInSelection();
if (findFirst) {
SearchReplaceUtilities.SelectText(textEditor, startOffset, endOffset);
}
}
} finally {
ignoreSelectionChanges = false;
}
}
}
}

Loading…
Cancel
Save