#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

502 lines
16 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using ICSharpCode.SharpDevelop.Editor;
using System;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.XmlForms;
namespace SearchAndReplace
{
class StoredSelection
{
public readonly int Offset, Length;
public int EndOffset {
get { return Offset + Length; }
}
public bool IsTextSelected {
get { return Length > 0; }
}
public StoredSelection(int offset, int length)
{
this.Offset = offset;
this.Length = length;
}
}
public class SearchAndReplacePanel : BaseSharpDevelopUserControl
{
SearchAndReplaceMode searchAndReplaceMode;
StoredSelection selection;
ITextEditor textEditor;
bool ignoreSelectionChanges;
bool findFirst;
public SearchAndReplaceMode SearchAndReplaceMode {
get {
return searchAndReplaceMode;
}
set {
searchAndReplaceMode = value;
SuspendLayout();
Controls.Clear();
switch (searchAndReplaceMode) {
case SearchAndReplaceMode.Search:
SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("SearchAndReplace.Resources.FindPanel.xfrm"));
Get<Button>("bookmarkAll").Click += BookmarkAllButtonClicked;
Get<Button>("findAll").Click += FindAllButtonClicked;
this.ParentForm.AcceptButton = Get<Button>("findNext");
break;
case SearchAndReplaceMode.Replace:
SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("SearchAndReplace.Resources.ReplacePanel.xfrm"));
Get<Button>("replace").Click += ReplaceButtonClicked;
Get<Button>("replaceAll").Click += ReplaceAllButtonClicked;
this.ParentForm.AcceptButton = Get<Button>("replace");
break;
}
Get<ComboBox>("find").TextChanged += FindPatternChanged;
ControlDictionary["findNextButton"].Click += FindNextButtonClicked;
ControlDictionary["lookInBrowseButton"].Click += LookInBrowseButtonClicked;
((Form)Parent).AcceptButton = (Button)ControlDictionary["findNextButton"];
SetOptions();
EnableButtons(HasFindPattern);
RightToLeftConverter.ReConvertRecursive(this);
ResumeLayout(false);
}
}
public SearchAndReplacePanel()
{
}
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)
{
ComboBox lookinComboBox = Get<ComboBox>("lookIn");
using (FolderBrowserDialog dlg = FileService.CreateFolderBrowserDialog("${res:Dialog.NewProject.SearchReplace.LookIn.SelectDirectory}", lookinComboBox.Text)) {
if (dlg.ShowDialog() == DialogResult.OK) {
lookinComboBox.SelectedIndex = customDirectoryIndex;
lookinComboBox.Text = dlg.SelectedPath;
}
}
}
void FindNextButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
FindNextInSelection();
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
SearchReplaceManager.FindNext(monitor);
}
}
Focus();
}
void FindAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
RunAllInSelection(0);
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
SearchInFilesManager.FindAll(monitor);
}
}
}
void BookmarkAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
RunAllInSelection(1);
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
SearchReplaceManager.MarkAll(monitor);
}
}
}
void ReplaceAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
RunAllInSelection(2);
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
SearchReplaceManager.ReplaceAll(monitor);
}
}
}
void ReplaceButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
if (IsSelectionSearch) {
if (selection.IsTextSelected) {
ReplaceInSelection();
}
} else {
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true))
{
monitor.Progress = double.NaN; // progress not implemented, use indeterminate progress
SearchReplaceManager.Replace(monitor);
}
}
Focus();
}
void WritebackOptions()
{
SearchOptions.FindPattern = Get<ComboBox>("find").Text;
if (searchAndReplaceMode == SearchAndReplaceMode.Replace) {
SearchOptions.ReplacePattern = Get<ComboBox>("replace").Text;
}
if (Get<ComboBox>("lookIn").DropDownStyle == ComboBoxStyle.DropDown) {
SearchOptions.LookIn = Get<ComboBox>("lookIn").Text;
}
SearchOptions.LookInFiletypes = Get<ComboBox>("fileTypes").Text;
SearchOptions.MatchCase = Get<CheckBox>("matchCase").Checked;
SearchOptions.MatchWholeWord = Get<CheckBox>("matchWholeWord").Checked;
SearchOptions.IncludeSubdirectories = Get<CheckBox>("includeSubFolder").Checked;
SearchOptions.SearchStrategyType = (SearchStrategyType)Get<ComboBox>("use").SelectedIndex;
if (Get<ComboBox>("lookIn").DropDownStyle == ComboBoxStyle.DropDown) {
SearchOptions.DocumentIteratorType = DocumentIteratorType.Directory;
} else {
SearchOptions.DocumentIteratorType = (DocumentIteratorType)Get<ComboBox>("lookIn").SelectedIndex;
}
}
const int customDirectoryIndex = 5;
void SetOptions()
{
Get<ComboBox>("find").Text = SearchOptions.FindPattern;
Get<ComboBox>("find").Items.Clear();
Get<ComboBox>("find").Text = SearchOptions.FindPattern;
Get<ComboBox>("find").Items.Clear();
foreach (string findPattern in SearchOptions.FindPatterns) {
Get<ComboBox>("find").Items.Add(findPattern);
}
if (searchAndReplaceMode == SearchAndReplaceMode.Replace) {
Get<ComboBox>("replace").Text = SearchOptions.ReplacePattern;
Get<ComboBox>("replace").Items.Clear();
foreach (string replacePattern in SearchOptions.ReplacePatterns) {
Get<ComboBox>("replace").Items.Add(replacePattern);
}
}
Get<ComboBox>("lookIn").Text = SearchOptions.LookIn;
string[] lookInTexts = {
// must be in the same order as the DocumentIteratorType enum
"${res:Dialog.NewProject.SearchReplace.LookIn.CurrentDocument}",
"${res:Dialog.NewProject.SearchReplace.LookIn.CurrentSelection}",
"${res:Dialog.NewProject.SearchReplace.LookIn.AllOpenDocuments}",
"${res:Dialog.NewProject.SearchReplace.LookIn.WholeProject}",
"${res:Dialog.NewProject.SearchReplace.LookIn.WholeSolution}"
};
foreach (string lookInText in lookInTexts) {
Get<ComboBox>("lookIn").Items.Add(StringParser.Parse(lookInText));
}
Get<ComboBox>("lookIn").Items.Add(SearchOptions.LookIn);
Get<ComboBox>("lookIn").SelectedIndexChanged += new EventHandler(LookInSelectedIndexChanged);
if (IsMultipleLineSelection(SearchReplaceUtilities.GetActiveTextEditor())) {
DocumentIteratorType = DocumentIteratorType.CurrentSelection;
} else {
if (SearchOptions.DocumentIteratorType == DocumentIteratorType.CurrentSelection) {
SearchOptions.DocumentIteratorType = DocumentIteratorType.CurrentDocument;
}
DocumentIteratorType = SearchOptions.DocumentIteratorType;
}
Get<ComboBox>("fileTypes").Text = SearchOptions.LookInFiletypes;
Get<CheckBox>("matchCase").Checked = SearchOptions.MatchCase;
Get<CheckBox>("matchWholeWord").Checked = SearchOptions.MatchWholeWord;
Get<CheckBox>("includeSubFolder").Checked = SearchOptions.IncludeSubdirectories;
Get<ComboBox>("use").Items.Clear();
Get<ComboBox>("use").Items.Add(StringParser.Parse("${res:Dialog.NewProject.SearchReplace.SearchStrategy.Standard}"));
Get<ComboBox>("use").Items.Add(StringParser.Parse("${res:Dialog.NewProject.SearchReplace.SearchStrategy.RegexSearch}"));
Get<ComboBox>("use").Items.Add(StringParser.Parse("${res:Dialog.NewProject.SearchReplace.SearchStrategy.WildcardSearch}"));
switch (SearchOptions.SearchStrategyType) {
case SearchStrategyType.RegEx:
Get<ComboBox>("use").SelectedIndex = 1;
break;
case SearchStrategyType.Wildcard:
Get<ComboBox>("use").SelectedIndex = 2;
break;
default:
Get<ComboBox>("use").SelectedIndex = 0;
break;
}
}
void LookInSelectedIndexChanged(object sender, EventArgs e)
{
if (Get<ComboBox>("lookIn").SelectedIndex == customDirectoryIndex) {
Get<ComboBox>("lookIn").DropDownStyle = ComboBoxStyle.DropDown;
Get<CheckBox>("includeSubFolder").Enabled = true;
Get<ComboBox>("fileTypes").Enabled = true;
Get<Label>("lookAtTypes").Enabled = true;
} else {
Get<ComboBox>("lookIn").DropDownStyle = ComboBoxStyle.DropDownList;
Get<CheckBox>("includeSubFolder").Enabled = false;
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>
static bool IsMultipleLineSelection(ITextEditor editor)
{
if (editor == null)
return false;
else
return editor.SelectedText.IndexOf('\n') != -1;
}
void FindNextInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
if (findFirst) {
textEditor.Caret.Offset = startOffset;
}
try {
ignoreSelectionChanges = true;
if (findFirst) {
findFirst = false;
SearchReplaceManager.FindFirstInSelection(startOffset, endOffset - startOffset, null);
} else {
findFirst = !SearchReplaceManager.FindNextInSelection(null);
if (findFirst) {
textEditor.Select(startOffset, endOffset - startOffset);
}
}
} finally {
ignoreSelectionChanges = false;
}
}
/// <summary>
/// Returns the first ISelection object from the currently active text editor
/// </summary>
static StoredSelection GetCurrentTextSelection()
{
ITextEditor textArea = SearchReplaceUtilities.GetActiveTextEditor();
if (textArea != null) {
return new StoredSelection(textArea.SelectionStart, textArea.SelectionLength);
}
return null;
}
void WorkbenchActiveViewContentChanged(object source, EventArgs e)
{
ITextEditor activeTextEditorControl = SearchReplaceUtilities.GetActiveTextEditor();
if (activeTextEditorControl != this.textEditor) {
AddSelectionChangedHandler(activeTextEditorControl);
TextSelectionChanged(source, e);
}
}
void AddSelectionChangedHandler(ITextEditor textEditor)
{
RemoveSelectionChangedHandler();
this.textEditor = textEditor;
if (textEditor != null) {
this.textEditor.SelectionChanged += TextSelectionChanged;
}
}
void RemoveSelectionChangedHandler()
{
if (textEditor != null) {
textEditor.SelectionChanged -= TextSelectionChanged;
}
}
void RemoveActiveWindowChangedHandler()
{
WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchActiveViewContentChanged;
}
/// <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 InitSelectionSearch()
{
findFirst = true;
selection = GetCurrentTextSelection();
AddSelectionChangedHandler(SearchReplaceUtilities.GetActiveTextEditor());
WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged;
}
void RemoveSelectionSearchHandlers()
{
RemoveSelectionChangedHandler();
RemoveActiveWindowChangedHandler();
}
/// <summary>
/// action: 0 = find, 1 = mark, 2 = replace
/// </summary>
void RunAllInSelection(int action)
{
const IProgressMonitor monitor = null;
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
textEditor.Select(startOffset, endOffset - startOffset);
try {
ignoreSelectionChanges = true;
if (action == 0)
SearchInFilesManager.FindAll(startOffset, endOffset - startOffset, monitor);
else if (action == 1)
SearchReplaceManager.MarkAll(startOffset, endOffset - startOffset, monitor);
else if (action == 2)
SearchReplaceManager.ReplaceAll(startOffset, endOffset - startOffset, monitor);
textEditor.Select(startOffset, endOffset - startOffset);
} finally {
ignoreSelectionChanges = false;
}
}
void ReplaceInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
if (findFirst) {
textEditor.Caret.Offset = startOffset;
}
try {
ignoreSelectionChanges = true;
if (findFirst) {
findFirst = false;
SearchReplaceManager.ReplaceFirstInSelection(startOffset, endOffset - startOffset, null);
} else {
findFirst = !SearchReplaceManager.ReplaceNextInSelection(null);
if (findFirst) {
textEditor.Select(startOffset, endOffset - startOffset);
}
}
} finally {
ignoreSelectionChanges = false;
}
}
/// <summary>
/// Enables the various find, bookmark and replace buttons
/// depending on whether any find string has been entered. The buttons
/// are disabled otherwise.
/// </summary>
void EnableButtons(bool enabled)
{
if (searchAndReplaceMode == SearchAndReplaceMode.Replace) {
Get<Button>("replace").Enabled = enabled;
Get<Button>("replaceAll").Enabled = enabled;
} else {
Get<Button>("bookmarkAll").Enabled = enabled;
Get<Button>("findAll").Enabled = enabled;
}
ControlDictionary["findNextButton"].Enabled = enabled;
}
/// <summary>
/// Returns true if the string entered in the find or replace text box
/// is not an empty string.
/// </summary>
bool HasFindPattern {
get {
return Get<ComboBox>("find").Text.Length != 0;
}
}
/// <summary>
/// Updates the enabled/disabled state of the search and replace buttons
/// after the search or replace text has changed.
/// </summary>
void FindPatternChanged(object source, EventArgs e)
{
EnableButtons(HasFindPattern);
}
}
}