Browse Source

Implemented syntax highlighting in search results pad.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4207 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
5eee3babfc
  1. 3
      src/AddIns/Misc/SearchAndReplace/Project/Gui/ResultsTreeView.xaml
  2. 61
      src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchResultNode.cs
  3. 10
      src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj
  4. 176
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightedInlineBuilder.cs
  5. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

3
src/AddIns/Misc/SearchAndReplace/Project/Gui/ResultsTreeView.xaml

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
<TreeView x:Class="SearchAndReplace.ResultsTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
VirtualizingStackPanel.IsVirtualizing="True">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">

61
src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchResultNode.cs

@ -5,14 +5,16 @@ @@ -5,14 +5,16 @@
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop;
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.Search;
@ -23,19 +25,50 @@ namespace SearchAndReplace @@ -23,19 +25,50 @@ namespace SearchAndReplace
/// </summary>
sealed class SearchResultNode : SearchNode
{
static readonly FontFamily resultLineFamily = new FontFamily("Consolas, Courier New");
SearchResultMatch result;
int lineNumber, column;
string resultText;
HighlightedInlineBuilder inlineBuilder;
public SearchResultNode(SearchResultMatch result)
{
this.result = result;
IDocument document = result.CreateDocument();
IDocumentLine matchedLine = document.GetLineForOffset(result.Offset);
lineNumber = matchedLine.LineNumber;
column = result.Offset - matchedLine.Offset + 1;
resultText = matchedLine.Text;
var startPosition = result.GetStartPosition(document);
this.lineNumber = startPosition.Line;
this.column = startPosition.Column;
if (lineNumber >= 1 && lineNumber <= document.TotalNumberOfLines) {
IDocumentLine matchedLine = document.GetLine(lineNumber);
inlineBuilder = new HighlightedInlineBuilder(matchedLine.Text);
inlineBuilder.SetFontFamily(0, inlineBuilder.Text.Length, resultLineFamily);
DocumentHighlighter highlighter = document.GetService(typeof(DocumentHighlighter)) as DocumentHighlighter;
TextDocument textDocument = document.GetService(typeof(TextDocument)) as TextDocument;
if (highlighter != null && textDocument != null) {
HighlightedLine highlightedLine = highlighter.HighlightLine(textDocument.GetLineByNumber(lineNumber));
int startOffset = highlightedLine.DocumentLine.Offset;
// copy only the foreground color
foreach (HighlightedSection section in highlightedLine.Sections) {
if (section.Color.Foreground != null) {
inlineBuilder.SetForeground(section.Offset - startOffset, section.Length, section.Color.Foreground.GetBrush(null));
}
}
}
// now highlight the match in bold
if (column >= 1) {
var endPosition = result.GetEndPosition(document);
if (endPosition.Line == startPosition.Line && endPosition.Column > startPosition.Column) {
// subtract one from the column to get the offset inside the line's text
int startOffset = column - 1;
int endOffset = Math.Min(inlineBuilder.Text.Length, endPosition.Column - 1);
inlineBuilder.SetFontWeight(startOffset, endOffset - startOffset, FontWeights.Bold);
}
}
}
}
bool showFileName = true;
@ -52,21 +85,19 @@ namespace SearchAndReplace @@ -52,21 +85,19 @@ namespace SearchAndReplace
}
}
static readonly FontFamily resultLineFamily = new FontFamily("Consolas, Courier New");
protected override object CreateText()
{
string displayText = result.DisplayText;
if (displayText != null)
return displayText;
LoggingService.Debug("Creating text for search result (" + lineNumber + ", " + column + ") ");
TextBlock textBlock = new TextBlock();
textBlock.Inlines.Add("(" + lineNumber + ", " + column + ")\t");
Span resultLineSpan = new Span();
resultLineSpan.FontFamily = resultLineFamily;
resultLineSpan.Inlines.Add(resultText);
textBlock.Inlines.Add(resultLineSpan);
string displayText = result.DisplayText;
if (displayText != null) {
textBlock.Inlines.Add(displayText);
} else if (inlineBuilder != null) {
textBlock.Inlines.AddRange(inlineBuilder.CreateInlines());
}
if (showFileName) {
textBlock.Inlines.Add(

10
src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj

@ -107,6 +107,16 @@ @@ -107,6 +107,16 @@
<Folder Include="Engine\TextIterator" />
<Folder Include="Gui" />
<Folder Include="Resources" />
<ProjectReference Include="..\..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\Project\NRefactory.csproj">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>
<Name>NRefactory</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj">
<Project>{2748AD25-9C63-4E12-877B-4DCE96FBED54}</Project>
<Name>ICSharpCode.SharpDevelop</Name>

176
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightedInlineBuilder.cs

@ -0,0 +1,176 @@ @@ -0,0 +1,176 @@
/*
* Created by SharpDevelop.
* User: Daniel
* Date: 02.06.2009
* Time: 21:33
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace ICSharpCode.AvalonEdit.Highlighting
{
/// <summary>
/// Takes a series of highlighting commands and stores them.
/// Later, it can build inline objects (for use with WPF TextBlock) from the commands.
/// </summary>
/// <remarks>
/// This class is not used in AvalonEdit - but it is useful for someone who wants to put a HighlightedLine
/// into a TextBlock.
/// In SharpDevelop, we use it to provide syntax highlighting inside the search results pad.
/// </remarks>
public sealed class HighlightedInlineBuilder
{
sealed class HighlightingState
{
internal Brush Foreground;
internal FontFamily Family;
internal FontWeight? Weight;
internal FontStyle? Style;
public HighlightingState Clone()
{
return new HighlightingState {
Foreground = this.Foreground,
Family = this.Family,
Weight = this.Weight,
Style = this.Style
};
}
}
readonly string text;
List<int> stateChangeOffsets = new List<int>();
List<HighlightingState> stateChanges = new List<HighlightingState>();
int GetIndexForOffset(int offset)
{
if (offset < 0 || offset > text.Length)
throw new ArgumentOutOfRangeException();
int index = stateChangeOffsets.BinarySearch(offset);
if (index < 0) {
index = ~index;
if (offset < text.Length) {
stateChanges.Insert(index, stateChanges[index - 1].Clone());
stateChangeOffsets.Insert(index, offset);
}
}
return index;
}
/// <summary>
/// Creates a new HighlightedInlineBuilder instance.
/// </summary>
public HighlightedInlineBuilder(string text)
{
if (text == null)
throw new ArgumentNullException("text");
this.text = text;
stateChangeOffsets.Add(0);
stateChanges.Add(new HighlightingState());
}
/// <summary>
/// Gets the text.
/// </summary>
public string Text {
get { return text; }
}
/// <summary>
/// Applies the properties from the HighlightingColor to the specified text segment.
/// </summary>
public void SetHighlighting(int offset, int length, HighlightingColor color)
{
int startIndex = GetIndexForOffset(offset);
int endIndex = GetIndexForOffset(offset + length);
for (int i = startIndex; i < endIndex; i++) {
HighlightingState state = stateChanges[i];
if (color.Foreground != null)
state.Foreground = color.Foreground.GetBrush(null);
if (color.FontStyle != null)
state.Style = color.FontStyle;
if (color.FontWeight != null)
state.Weight = color.FontWeight;
}
}
/// <summary>
/// Sets the foreground brush on the specified text segment.
/// </summary>
public void SetForeground(int offset, int length, Brush brush)
{
int startIndex = GetIndexForOffset(offset);
int endIndex = GetIndexForOffset(offset + length);
for (int i = startIndex; i < endIndex; i++) {
stateChanges[i].Foreground = brush;
}
}
/// <summary>
/// Sets the font weight on the specified text segment.
/// </summary>
public void SetFontWeight(int offset, int length, FontWeight weight)
{
int startIndex = GetIndexForOffset(offset);
int endIndex = GetIndexForOffset(offset + length);
for (int i = startIndex; i < endIndex; i++) {
stateChanges[i].Weight = weight;
}
}
/// <summary>
/// Sets the font style on the specified text segment.
/// </summary>
public void SetFontStyle(int offset, int length, FontStyle style)
{
int startIndex = GetIndexForOffset(offset);
int endIndex = GetIndexForOffset(offset + length);
for (int i = startIndex; i < endIndex; i++) {
stateChanges[i].Style = style;
}
}
/// <summary>
/// Sets the font family on the specified text segment.
/// </summary>
public void SetFontFamily(int offset, int length, FontFamily family)
{
int startIndex = GetIndexForOffset(offset);
int endIndex = GetIndexForOffset(offset + length);
for (int i = startIndex; i < endIndex; i++) {
stateChanges[i].Family = family;
}
}
/// <summary>
/// Creates WPF Run instances that can be used for TextBlock.Inlines.
/// </summary>
public Run[] CreateInlines()
{
Run[] runs = new Run[stateChanges.Count];
for (int i = 0; i < runs.Length; i++) {
int startOffset = stateChangeOffsets[i];
int endOffset = i + 1 < stateChangeOffsets.Count ? stateChangeOffsets[i + 1] : text.Length;
Run r = new Run(text.Substring(startOffset, endOffset - startOffset));
HighlightingState state = stateChanges[i];
if (state.Foreground != null)
r.Foreground = state.Foreground;
if (state.Weight != null)
r.FontWeight = state.Weight.Value;
if (state.Family != null)
r.FontFamily = state.Family;
if (state.Style != null)
r.FontStyle = state.Style.Value;
runs[i] = r;
}
return runs;
}
}
}

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -164,6 +164,7 @@ @@ -164,6 +164,7 @@
<DependentUpon>IReadOnlySectionProvider.cs</DependentUpon>
</Compile>
<Compile Include="Highlighting\DocumentHighlighter.cs" />
<Compile Include="Highlighting\HighlightedInlineBuilder.cs" />
<Compile Include="Highlighting\HighlightedLine.cs" />
<Compile Include="Highlighting\HighlightedSection.cs" />
<Compile Include="Highlighting\HighlightingBrush.cs" />

Loading…
Cancel
Save