Browse Source

add basic Search API and Search Options to SearchPanel

pull/23/head
Siegfried Pammer 15 years ago
parent
commit
932fd5ad47
  1. 22
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextSegmentCollection.cs
  2. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs
  3. 24
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs
  4. 9
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  5. 52
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/DefaultSearchStrategy.cs
  6. 60
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/DropDownButton.cs
  7. 71
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/DropDownButton.xaml
  8. 22
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs
  9. 32
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchCommands.cs
  10. 31
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchPanel.xaml
  11. 114
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchPanel.xaml.cs
  12. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchResultBackgroundRenderer.cs
  13. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/themes/generic.xaml

22
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextSegmentCollection.cs

@ -267,7 +267,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -267,7 +267,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary>
/// Gets the previous segment before the specified segment.
/// Segments are sorted by their start offset.
/// Returns null if segment is the last segment.
/// Returns null if segment is the first segment.
/// </summary>
public T GetPreviousSegment(T segment)
{
@ -277,6 +277,26 @@ namespace ICSharpCode.AvalonEdit.Document @@ -277,6 +277,26 @@ namespace ICSharpCode.AvalonEdit.Document
}
#endregion
#region FirstSegment/LastSegment
/// <summary>
/// Returns the first segment in the collection or null, if the collection is empty.
/// </summary>
public T FirstSegment {
get {
return root == null ? null : (T)root.LeftMost;
}
}
/// <summary>
/// Returns the last segment in the collection or null, if the collection is empty.
/// </summary>
public T LastSegment {
get {
return root == null ? null : (T)root.RightMost;
}
}
#endregion
#region FindFirstSegmentWithStartAfter
/// <summary>
/// Gets the first segment with a start offset greater or equal to <paramref name="startOffset"/>.

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs

@ -12,9 +12,9 @@ using System.Text; @@ -12,9 +12,9 @@ using System.Text;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Search;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Editing

24
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs

@ -2,8 +2,10 @@ @@ -2,8 +2,10 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Search;
@ -41,6 +43,8 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -41,6 +43,8 @@ namespace ICSharpCode.AvalonEdit.Editing
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, ExecuteUndo, CanExecuteUndo));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, ExecuteRedo, CanExecuteRedo));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Find, ExecuteFind));
this.CommandBindings.Add(new CommandBinding(SearchCommands.FindNext, ExecuteFindNext));
this.CommandBindings.Add(new CommandBinding(SearchCommands.FindPrevious, ExecuteFindPrevious));
}
internal static KeyBinding CreateFrozenKeyBinding(ICommand command, ModifierKeys modifiers, Key key)
@ -109,7 +113,25 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -109,7 +113,25 @@ namespace ICSharpCode.AvalonEdit.Editing
void ExecuteFind(object sender, ExecutedRoutedEventArgs e)
{
new SearchPanel(TextArea);
var panel = TextArea.TextView.Layers.OfType<SearchPanel>().FirstOrDefault();
if (panel == null)
new SearchPanel(TextArea);
else
panel.Reactivate();
}
void ExecuteFindNext(object sender, ExecutedRoutedEventArgs e)
{
var panel = TextArea.TextView.Layers.OfType<SearchPanel>().FirstOrDefault();
if (panel != null)
panel.FindNext();
}
void ExecuteFindPrevious(object sender, ExecutedRoutedEventArgs e)
{
var panel = TextArea.TextView.Layers.OfType<SearchPanel>().FirstOrDefault();
if (panel != null)
panel.FindPrevious();
}
}
}

9
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -290,7 +290,11 @@ @@ -290,7 +290,11 @@
<Compile Include="Rendering\VisualYPosition.cs">
<DependentUpon>VisualLine.cs</DependentUpon>
</Compile>
<Compile Include="Search\SearchPanel.cs" />
<Compile Include="Search\DefaultSearchStrategy.cs" />
<Compile Include="Search\DropDownButton.cs" />
<Compile Include="Search\ISearchStrategy.cs" />
<Compile Include="Search\SearchCommands.cs" />
<Compile Include="Search\SearchResultBackgroundRenderer.cs" />
<Compile Include="Search\SearchPanel.xaml.cs">
<DependentUpon>SearchPanel.xaml</DependentUpon>
<SubType>Code</SubType>
@ -412,6 +416,9 @@ @@ -412,6 +416,9 @@
<Page Include="CodeCompletion\CompletionList.xaml" />
<Page Include="CodeCompletion\InsightWindow.xaml" />
<Page Include="Search\SearchPanel.xaml" />
<Page Include="Search\DropDownButton.xaml">
<DependentUpon>DropDownButton.cs</DependentUpon>
</Page>
<Page Include="TextEditor.xaml" />
<Page Include="themes\generic.xaml" />
</ItemGroup>

52
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/DefaultSearchStrategy.cs

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
// 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 System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Search
{
class DefaultSearchStrategy : ISearchStrategy
{
readonly Regex searchPattern;
public DefaultSearchStrategy(Regex searchPattern)
{
this.searchPattern = searchPattern;
}
public static ISearchStrategy Create(string searchPattern, bool ignoreCase, bool useRegularExpressions, bool matchWholeWords)
{
RegexOptions options = RegexOptions.Compiled;
if (ignoreCase)
options |= RegexOptions.IgnoreCase;
if (!useRegularExpressions)
searchPattern = Regex.Escape(searchPattern);
if (matchWholeWords)
searchPattern = "\\b" + searchPattern + "\\b";
Regex pattern = new Regex(searchPattern, options);
return new DefaultSearchStrategy(pattern);
}
public IEnumerable<ISearchResult> FindAll(ITextSource document)
{
foreach (Match result in searchPattern.Matches(document.Text)) {
yield return new SearchResult { StartOffset = result.Index, Length = result.Length };
}
}
}
}

60
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/DropDownButton.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
// 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 System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace ICSharpCode.AvalonEdit.Search
{
/// <summary>
/// A button that opens a drop-down menu when clicked.
/// </summary>
class DropDownButton : ButtonBase
{
public static readonly DependencyProperty DropDownContentProperty
= DependencyProperty.Register("DropDownContent", typeof(Popup),
typeof(DropDownButton), new FrameworkPropertyMetadata(null));
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
protected static readonly DependencyPropertyKey IsDropDownContentOpenPropertyKey
= DependencyProperty.RegisterReadOnly("IsDropDownContentOpen", typeof(bool),
typeof(DropDownButton), new FrameworkPropertyMetadata(false));
public static readonly DependencyProperty IsDropDownContentOpenProperty = IsDropDownContentOpenPropertyKey.DependencyProperty;
static DropDownButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DropDownButton), new FrameworkPropertyMetadata(typeof(DropDownButton)));
}
public Popup DropDownContent {
get { return (Popup)GetValue(DropDownContentProperty); }
set { SetValue(DropDownContentProperty, value); }
}
public bool IsDropDownContentOpen {
get { return (bool)GetValue(IsDropDownContentOpenProperty); }
protected set { SetValue(IsDropDownContentOpenPropertyKey, value); }
}
protected override void OnClick()
{
if (DropDownContent != null && !IsDropDownContentOpen) {
DropDownContent.Placement = PlacementMode.Bottom;
DropDownContent.PlacementTarget = this;
DropDownContent.IsOpen = true;
DropDownContent.Closed += DropDownContent_Closed;
this.IsDropDownContentOpen = true;
}
}
void DropDownContent_Closed(object sender, EventArgs e)
{
((Popup)sender).Closed -= DropDownContent_Closed;
this.IsDropDownContentOpen = false;
}
}
}

71
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/DropDownButton.xaml

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.AvalonEdit.Search"
>
<!-- Colors for DropDownButton and SplitButton -->
<SolidColorBrush x:Key="{ComponentResourceKey {x:Type local:DropDownButton}, ActiveBorder}" Color="#FF0A246A"/>
<SolidColorBrush x:Key="{ComponentResourceKey {x:Type local:DropDownButton}, ActiveBackground}" Color="#FFB6BDD2"/>
<!-- Style and Template for DropDownButton -->
<Style TargetType="{x:Type local:DropDownButton}">
<Setter Property="TextElement.Foreground" Value = "{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Control.Padding" Value="2,2,2,2"/>
<Setter Property="Border.BorderThickness" Value="1,1,1,1"/>
<Setter Property="Panel.Background" Value="Transparent"/>
<Setter Property="Border.BorderBrush" Value="Transparent"/>
<Setter Property="FrameworkElement.HorizontalAlignment" Value="Center"/>
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center"/>
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
<Setter Property="Control.VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:DropDownButton"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="OuterBorder"
SnapsToDevicePixels="True"
>
<StackPanel Orientation="Horizontal">
<ContentPresenter
Margin="{TemplateBinding Control.Padding}"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
<Path Margin="0,2,2,2"
Data = "M0,0 L1,0 0.5,1 z"
Fill = "{TemplateBinding TextElement.Foreground}"
Width = "7"
Height = "3.5"
Stretch = "Fill"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="{DynamicResource {ComponentResourceKey {x:Type local:DropDownButton}, ActiveBorder}}" />
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="{DynamicResource {ComponentResourceKey {x:Type local:DropDownButton}, ActiveBackground}}"/>
</Trigger>
<Trigger Property="UIElement.IsKeyboardFocused" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="{DynamicResource {ComponentResourceKey {x:Type local:DropDownButton}, ActiveBorder}}"/>
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="{DynamicResource {ComponentResourceKey {x:Type local:DropDownButton}, ActiveBackground}}"/>
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="local:DropDownButton.IsDropDownContentOpen" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
<Setter Property="Border.BorderThickness" TargetName="OuterBorder" Value="1,1,1,0" />
<Setter Property="Border.Padding" TargetName="OuterBorder" Value="0,0,0,1" />
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

22
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/ISearchStrategy.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// 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 System;
using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Document;
namespace ICSharpCode.AvalonEdit.Search
{
/// <summary>
/// Description of ISearchStrategy.
/// </summary>
public interface ISearchStrategy
{
IEnumerable<ISearchResult> FindAll(ITextSource document);
}
public interface ISearchResult : ISegment
{
}
}

32
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchCommands.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
// 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 System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Search
{
public static class SearchCommands
{
public static readonly RoutedCommand FindNext = new RoutedCommand(
"FindNext", typeof(SearchPanel),
new InputGestureCollection { new KeyGesture(Key.F3) }
);
public static readonly RoutedCommand FindPrevious = new RoutedCommand(
"FindPrevious", typeof(SearchPanel),
new InputGestureCollection { new KeyGesture(Key.F3, ModifierKeys.Control) }
);
}
class SearchResult : TextSegment, ISearchResult
{
}
}

31
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchPanel.xaml

@ -1,24 +1,37 @@ @@ -1,24 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl x:Class="ICSharpCode.AvalonEdit.Search.SearchPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl x:Class="ICSharpCode.AvalonEdit.Search.SearchPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ICSharpCode.AvalonEdit.Search" FocusManager.IsFocusScope="True" PreviewKeyDown="SearchLayerKeyDown">
<UserControl.Resources>
<BitmapImage x:Key="PrevImage" UriSource="prev.png" />
<BitmapImage x:Key="NextImage" UriSource="next.png" />
</UserControl.Resources>
<Border Background="WhiteSmoke" HorizontalAlignment="Right" VerticalAlignment="Top" Cursor="Arrow">
<Border Background="White" BorderBrush="DimGray" BorderThickness="1" HorizontalAlignment="Right" VerticalAlignment="Top" Cursor="Arrow">
<StackPanel Orientation="Horizontal" Margin="3">
<TextBox Name="searchTextBox" Focusable="True" Width="100" Height="24" Margin="3,3,3,0" TextChanged="SearchTextBoxTextChanged" PreviewKeyDown="SearchLayerKeyDown" />
<local:DropDownButton Height="24">
<local:DropDownButton.DropDownContent>
<Popup StaysOpen="False">
<Border Background="White" BorderBrush="DimGray" BorderThickness="1">
<StackPanel Orientation="Vertical">
<CheckBox x:FieldModifier="private" x:Name="matchCase" Content="Match case" Margin="3" />
<CheckBox x:FieldModifier="private" x:Name="wholeWords" Content="Match whole words" Margin="3" />
<CheckBox x:FieldModifier="private" x:Name="useRegex" Content="Use Regular Expressions" Margin="3" />
</StackPanel>
</Border>
</Popup>
</local:DropDownButton.DropDownContent>
</local:DropDownButton>
<Button Margin="3" Height="24" Width="24" Command="local:SearchCommands.FindPrevious" ToolTip="Find Next (Ctrl+F3)">
<Image Width="16" Height="16" Stretch="Fill" Source="{StaticResource PrevImage}" />
</Button>
<Button Margin="3" Height="24" Width="24" Command="local:SearchCommands.FindNext" ToolTip="Find Next (F3)">
<Image Width="16" Height="16" Stretch="Fill" Source="{StaticResource NextImage}" />
</Button>
<Button Click="CloseClick" Margin="3" Height="16" Width="16" VerticalContentAlignment="Top" HorizontalContentAlignment="Left">
<Grid>
<Line X1="2" Y1="2" X2="8" Y2="8" Stroke="Black" StrokeThickness="1" />
<Line X1="8" Y1="2" X2="2" Y2="8" Stroke="Black" StrokeThickness="1" />
</Grid>
</Button>
<TextBox Name="searchTextBox" Width="100" Height="24" Margin="3" TextChanged="SearchTextBoxTextChanged" />
<Button Margin="3" Height="24" Width="24" Click="PrevClick">
<Image Width="16" Height="16" Stretch="Fill" Source="{StaticResource PrevImage}" />
</Button>
<Button Margin="3" Height="24" Width="24" Click="NextClick">
<Image Width="16" Height="16" Stretch="Fill" Source="{StaticResource NextImage}" />
</Button>
</StackPanel>
</Border>
</UserControl>

114
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchPanel.xaml.cs

@ -4,8 +4,10 @@ @@ -4,8 +4,10 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
@ -13,6 +15,7 @@ using System.Windows.Media; @@ -13,6 +15,7 @@ using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Search
@ -25,6 +28,11 @@ namespace ICSharpCode.AvalonEdit.Search @@ -25,6 +28,11 @@ namespace ICSharpCode.AvalonEdit.Search
TextArea textArea;
SearchResultBackgroundRenderer renderer;
SearchResult currentResult;
FoldingManager foldingManager;
public bool UseRegex { get { return useRegex.IsChecked == true; } }
public bool MatchCase { get { return matchCase.IsChecked == true; } }
public bool WholeWords { get { return wholeWords.IsChecked == true; } }
public SearchPanel(TextArea textArea)
{
@ -35,32 +43,77 @@ namespace ICSharpCode.AvalonEdit.Search @@ -35,32 +43,77 @@ namespace ICSharpCode.AvalonEdit.Search
InitializeComponent();
textArea.TextView.Layers.Add(this);
foldingManager = textArea.GetService(typeof(FoldingManager)) as FoldingManager;
renderer = new SearchResultBackgroundRenderer();
textArea.TextView.BackgroundRenderers.Add(renderer);
textArea.Document.TextChanged += delegate { DoSearch(false); };
this.Loaded += delegate { searchTextBox.Focus(); };
useRegex.Checked += delegate { DoSearch(true); };
matchCase.Checked += delegate { DoSearch(true); };
wholeWords.Checked += delegate { DoSearch(true); };
Dispatcher.Invoke(DispatcherPriority.Input, (Action)(() => searchTextBox.Focus()));
useRegex.Unchecked += delegate { DoSearch(true); };
matchCase.Unchecked += delegate { DoSearch(true); };
wholeWords.Unchecked += delegate { DoSearch(true); };
}
void SearchTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
DoSearch(true);
}
/// <summary>
/// Reactivates the SearchPanel by setting the focus on the search box and selecting all text.
/// </summary>
public void Reactivate()
{
searchTextBox.Focus();
searchTextBox.SelectAll();
}
public void FindNext()
{
SearchResult result = null;
if (currentResult != null)
result = renderer.CurrentResults.GetNextSegment(currentResult);
if (result == null)
result = renderer.CurrentResults.FirstSegment;
if (result != null) {
currentResult = result;
SetResult(result);
}
}
public void FindPrevious()
{
SearchResult result = null;
if (currentResult != null)
result = renderer.CurrentResults.GetPreviousSegment(currentResult);
if (result == null)
result = renderer.CurrentResults.LastSegment;
if (result != null) {
currentResult = result;
SetResult(result);
}
}
void DoSearch(bool changeSelection)
{
renderer.CurrentResults.Clear();
if (!string.IsNullOrEmpty(searchTextBox.Text)) {
ISearchStrategy strategy = DefaultSearchStrategy.Create(searchTextBox.Text, !MatchCase, UseRegex, WholeWords);
currentResult = null;
int offset = textArea.Caret.Offset;
foreach (var result in FindAll(searchTextBox.Text, textArea.Document)) {
if (changeSelection) {
textArea.Selection = SimpleSelection.Empty;
}
foreach (SearchResult result in strategy.FindAll(textArea.Document)) {
if (currentResult == null && result.StartOffset >= offset) {
currentResult = result;
if (changeSelection) {
textArea.Caret.Offset = currentResult.StartOffset;
textArea.Selection = new SimpleSelection(currentResult.StartOffset, currentResult.EndOffset);
SetResult(result);
}
}
renderer.CurrentResults.Add(result);
@ -68,32 +121,17 @@ namespace ICSharpCode.AvalonEdit.Search @@ -68,32 +121,17 @@ namespace ICSharpCode.AvalonEdit.Search
}
textArea.TextView.InvalidateLayer(KnownLayer.Selection);
}
IEnumerable<SearchResult> FindAll(string search, TextDocument document)
void SetResult(SearchResult result)
{
SearchResult lastResult = FindNext(search, 0, document);
while (lastResult != null) {
yield return lastResult;
lastResult = FindNext(search, lastResult.StartOffset + lastResult.Length, document);
textArea.Caret.Offset = currentResult.StartOffset;
textArea.Selection = new SimpleSelection(currentResult.StartOffset, currentResult.EndOffset);
if (foldingManager != null) {
foreach (var folding in foldingManager.GetFoldingsContaining(result.StartOffset))
folding.IsFolded = false;
}
}
SearchResult FindNext(string search, int index, TextDocument document)
{
int result = document.Text.IndexOf(search, index, StringComparison.OrdinalIgnoreCase);
if (result > -1)
return new SearchResult { StartOffset = result, Length = search.Length };
return null;
}
SearchResult FindPrev(string search, int index, TextDocument document)
{
int result = document.GetText(0, index).LastIndexOf(search, StringComparison.OrdinalIgnoreCase);
if (result > -1)
return new SearchResult { StartOffset = result, Length = search.Length };
return null;
}
void SearchLayerKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape) {
@ -106,27 +144,5 @@ namespace ICSharpCode.AvalonEdit.Search @@ -106,27 +144,5 @@ namespace ICSharpCode.AvalonEdit.Search
textArea.TextView.Layers.Remove(this);
textArea.TextView.BackgroundRenderers.Remove(renderer);
}
void PrevClick(object sender, RoutedEventArgs e)
{
if (currentResult != null) {
var result = FindPrev(searchTextBox.Text, currentResult.StartOffset, textArea.Document);
if (result != null) {
currentResult = result;
textArea.Selection = new SimpleSelection(currentResult.StartOffset, currentResult.EndOffset);
}
}
}
void NextClick(object sender, RoutedEventArgs e)
{
if (currentResult != null) {
var result = FindNext(searchTextBox.Text, currentResult.EndOffset, textArea.Document);
if (result != null) {
currentResult = result;
textArea.Selection = new SimpleSelection(currentResult.StartOffset, currentResult.EndOffset);
}
}
}
}
}

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchPanel.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchResultBackgroundRenderer.cs

@ -14,10 +14,6 @@ using ICSharpCode.AvalonEdit.Rendering; @@ -14,10 +14,6 @@ using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Search
{
class SearchResult : TextSegment
{
}
class SearchResultBackgroundRenderer : IBackgroundRenderer
{
TextSegmentCollection<SearchResult> currentResults = new TextSegmentCollection<SearchResult>();

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/themes/generic.xaml

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:editing="clr-namespace:ICSharpCode.AvalonEdit.Editing"
>
xmlns:editing="clr-namespace:ICSharpCode.AvalonEdit.Editing">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/TextEditor.xaml" />
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/Search/DropDownButton.xaml" />
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/CodeCompletion/CompletionList.xaml" />
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/CodeCompletion/InsightWindow.xaml" />
</ResourceDictionary.MergedDictionaries>

Loading…
Cancel
Save