6 changed files with 165 additions and 76 deletions
@ -0,0 +1,24 @@ |
|||||||
|
<?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.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"> |
||||||
|
<StackPanel Orientation="Horizontal" Margin="3"> |
||||||
|
<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> |
||||||
@ -0,0 +1,132 @@ |
|||||||
|
// 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.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
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.Rendering; |
||||||
|
|
||||||
|
namespace ICSharpCode.AvalonEdit.Search |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SearchPanel.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class SearchPanel : UserControl |
||||||
|
{ |
||||||
|
TextArea textArea; |
||||||
|
SearchResultBackgroundRenderer renderer; |
||||||
|
SearchResult currentResult; |
||||||
|
|
||||||
|
public SearchPanel(TextArea textArea) |
||||||
|
{ |
||||||
|
if (textArea == null) |
||||||
|
throw new ArgumentNullException("textArea"); |
||||||
|
this.textArea = textArea; |
||||||
|
|
||||||
|
InitializeComponent(); |
||||||
|
|
||||||
|
textArea.TextView.Layers.Add(this); |
||||||
|
|
||||||
|
renderer = new SearchResultBackgroundRenderer(); |
||||||
|
textArea.TextView.BackgroundRenderers.Add(renderer); |
||||||
|
textArea.Document.TextChanged += delegate { DoSearch(false); }; |
||||||
|
|
||||||
|
Dispatcher.Invoke(DispatcherPriority.Input, (Action)(() => searchTextBox.Focus())); |
||||||
|
} |
||||||
|
|
||||||
|
void SearchTextBoxTextChanged(object sender, TextChangedEventArgs e) |
||||||
|
{ |
||||||
|
DoSearch(true); |
||||||
|
} |
||||||
|
|
||||||
|
void DoSearch(bool changeSelection) |
||||||
|
{ |
||||||
|
renderer.CurrentResults.Clear(); |
||||||
|
if (!string.IsNullOrEmpty(searchTextBox.Text)) { |
||||||
|
|
||||||
|
currentResult = null; |
||||||
|
int offset = textArea.Caret.Offset; |
||||||
|
foreach (var result in FindAll(searchTextBox.Text, 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); |
||||||
|
} |
||||||
|
} |
||||||
|
renderer.CurrentResults.Add(result); |
||||||
|
} |
||||||
|
} |
||||||
|
textArea.TextView.InvalidateLayer(KnownLayer.Selection); |
||||||
|
} |
||||||
|
|
||||||
|
IEnumerable<SearchResult> FindAll(string search, TextDocument document) |
||||||
|
{ |
||||||
|
SearchResult lastResult = FindNext(search, 0, document); |
||||||
|
while (lastResult != null) { |
||||||
|
yield return lastResult; |
||||||
|
lastResult = FindNext(search, lastResult.StartOffset + lastResult.Length, document); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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) { |
||||||
|
CloseClick(sender, e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CloseClick(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in new issue