2017-02-06 14 views
1

私は現在、次のコードをAvalonEdit TextEditorLineTransformerとして使用しています。現在の単一の検索結果を選択肢で強調表示したいのですが、強調表示されたテキストの表示よりもDocumentColorizingTransformerの書式設定が優先されるため、選択範囲がほとんど見えません。強調表示された選択をフォーマットの代わりに、またはフォーマットの前に表示するにはどうすればよいですか?AvalonEditは他の書式よりも選択を選択します

public class ColorizeSearchResults : DocumentColorizingTransformer { 

    public ColorizeSearchResults() : base() { 
     SearchTerm = ""; 
     MatchCase = false; 
    } 

    public string SearchTerm { get; set; } 
    public bool MatchCase { get; set; } 

    protected override void ColorizeLine(DocumentLine line) { 
     if (SearchTerm.Length == 0) 
      return; 

     int lineStartOffset = line.Offset; 
     string text = CurrentContext.Document.GetText(line); 
     int count = 0; 
     int start = 0; 
     int index; 
     while ((index = text.IndexOf(SearchTerm, start, MatchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase)) >= 0) { 
      base.ChangeLinePart(
       lineStartOffset + index, 
       lineStartOffset + index + SearchTerm.Length, 
       (VisualLineElement element) => { 
        element.TextRunProperties.SetForegroundBrush(Brushes.White); 
        element.TextRunProperties.SetBackgroundBrush(Brushes.Magenta); 
       }); 
      start = index + 1; 
      count++; 
     } 
    } 
} 

Example of formatting showing over selection

答えて

0

私の最終製品は、既存のAvalonEdit SearchResultBackgroundRendererにほぼ完全に基づいています。

これは私の投稿の色付けツールとはちょっと違うので、検索結果を手動で修正する必要はありません。しかしそれは計算時間をいくらか節約するかもしれない。

検索でRegexを使用しない場合は、SearchResultを簡単に変更して、コンストラクタの開始オフセットと長さを渡すだけです。背景レンダラを利用するためには

/// <summary>A search result storing a match and text segment.</summary> 
public class SearchResult : TextSegment { 
    /// <summary>The regex match for the search result.</summary> 
    public Match Match { get; } 

    /// <summary>Constructs the search result from the match.</summary> 
    public SearchResult(Match match) { 
     this.StartOffset = match.Index; 
     this.Length = match.Length; 
     this.Match = match; 
    } 
} 

/// <summary>Colorizes search results behind the selection.</summary> 
public class ColorizeSearchResultsBackgroundRenderer : IBackgroundRenderer { 

    /// <summary>The search results to be modified.</summary> 
    TextSegmentCollection<SearchResult> currentResults = new TextSegmentCollection<SearchResult>(); 

    /// <summary>Constructs the search result colorizer.</summary> 
    public ColorizeSearchResultsBackgroundRenderer() { 
     Background = new SolidColorBrush(Color.FromRgb(246, 185, 77)); 
     Background.Freeze(); 
    } 

    /// <summary>Gets the layer on which this background renderer should draw.</summary> 
    public KnownLayer Layer { 
     get { 
      // draw behind selection 
      return KnownLayer.Selection; 
     } 
    } 

    /// <summary>Causes the background renderer to draw.</summary> 
    public void Draw(TextView textView, DrawingContext drawingContext) { 
     if (textView == null) 
      throw new ArgumentNullException("textView"); 
     if (drawingContext == null) 
      throw new ArgumentNullException("drawingContext"); 

     if (currentResults == null || !textView.VisualLinesValid) 
      return; 

     var visualLines = textView.VisualLines; 
     if (visualLines.Count == 0) 
      return; 

     int viewStart = visualLines.First().FirstDocumentLine.Offset; 
     int viewEnd = visualLines.Last().LastDocumentLine.EndOffset; 

     foreach (SearchResult result in currentResults.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { 
      BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder(); 
      geoBuilder.AlignToWholePixels = true; 
      geoBuilder.BorderThickness = 0; 
      geoBuilder.CornerRadius = 0; 
      geoBuilder.AddSegment(textView, result); 
      Geometry geometry = geoBuilder.CreateGeometry(); 
      if (geometry != null) { 
       drawingContext.DrawGeometry(Background, null, geometry); 
      } 
     } 
    } 

    /// <summary>Gets the search results for modification.</summary> 
    public TextSegmentCollection<SearchResult> CurrentResults { 
     get { return currentResults; } 
    } 

    /// <summary>Gets or sets the background brush for the search results.</summary> 
    public Brush Background { get; set; } 
} 

var searchColorizor = new ColorizeSearchResultsBackgroundRenderer(); 
textEditor.TextArea.TextView.BackgroundRenderers.Add(searchColorizor); 
1

AvalonEditが流れをレンダリングするためhttp://avalonedit.net/documentation/html/c06e9832-9ef0-4d65-ac2e-11f7ce9c7774.htmを参照してください。

選択レイヤーがテキストの前にレンダリングされます。したがって、テキストに背景がある場合は、選択背景が優先されます。幸いにも、背景をBrush.Transparent(またはSelection.Brushと独自の色の組み合わせ)に設定することができます。

ソリューション:私は透明に選択の背景をリセットするためにSelectionColorizerコードを変更した:

class SelectionColorizerWithBackground : ColorizingTransformer 
{ 
    ICSharpCode.AvalonEdit.Editing.TextArea _textArea; 

    public SelectionColorizerWithBackground(
     ICSharpCode.AvalonEdit.Editing.TextArea textArea) 
    { 
     if (textArea == null) 
      throw new ArgumentNullException("textArea"); 
     this._textArea = textArea; 
    } 

    protected override void Colorize(ITextRunConstructionContext context) 
    { 
     int lineStartOffset = context.VisualLine.FirstDocumentLine.Offset; 

     int lineEndOffset = context.VisualLine.LastDocumentLine.Offset + 
      context.VisualLine.LastDocumentLine.TotalLength; 

     foreach (var segment in _textArea.Selection.Segments) 
     { 
      int segmentStart = segment.StartOffset; 
      if (segmentStart >= lineEndOffset) 
       continue; 

      int segmentEnd = segment.EndOffset; 
      if (segmentEnd <= lineStartOffset) 
       continue; 

      int startColumn; 
      if (segmentStart < lineStartOffset) 
       startColumn = 0; 
      else 
       startColumn = context.VisualLine.ValidateVisualColumn(
        segment.StartOffset, segment.StartVisualColumn, 
        _textArea.Selection.EnableVirtualSpace); 

      int endColumn; 
      if (segmentEnd > lineEndOffset) 
       endColumn = 
        _textArea.Selection.EnableVirtualSpace 
         ? int.MaxValue 
         : context.VisualLine 
           .VisualLengthWithEndOfLineMarker; 
      else 
       endColumn = context.VisualLine.ValidateVisualColumn(
        segment.EndOffset, segment.EndVisualColumn, 
        _textArea.Selection.EnableVirtualSpace); 

      ChangeVisualElements(
       startColumn, endColumn, 
       element => { 
        element.TextRunProperties.SetBackgroundBrush(
         System.Windows.Media.Brushes.Transparent); 
        if (_textArea.SelectionForeground != null) 
        { 
         element.TextRunProperties.SetForegroundBrush(
          _textArea.SelectionForeground); 
        } 
       }); 
     } 
    } 
} 

あなたは、次の操作を行うことになっているコードを使用するには:私がした後

var lineTransformers = textEditor.TextArea.TextView.LineTransformers; 

// Remove the original SelectionColorizer. 
// Note: if you have syntax highlighting you need to do something else 
// to avoid clearing other colorizers. If too complicated you can skip 
// this step but to suffer a 2x performance penalty. 
lineTransformers.Clear(); 

lineTransformers.Add(new ColorizeSearchResults()); 
lineTransformers.Add(
    new SelectionColorizerWithBackground(textEditor.TextArea)); 
1

を私のソリューションを広範囲に試しましたが、いくつかの点を追加したいと思います:

  • 私の他のソル長方形がタイル張られていると思われる場合は、いくつかのサブピクセルアーチファクトが発生します。それが受け入れられない場合は、IBackgroundRendererを実装できます。 (私の選択した解決策になります。)いくつかのコードが必要な場合はここでリクエストできますが、それが有用かどうかは疑問です。

  • ところで、あなたの質問以来は、検索結果について(あなたが丸いボーダーをしたくない場合は、それを修正する)あなたはそのままhttps://github.com/icsharpcode/AvalonEdit/blob/697ff0d38c95c9e5a536fbc05ae2307ec9ef2a63/ICSharpCode.AvalonEdit/Search/SearchResultBackgroundRenderer.csを使用することができる可能性が高いです。

  • element.TextRunProperties.SetBackgroundBrush(Brushes.Magenta);の代わりにelement.BackgroundBrush = Brushes.Magenta;を使用できます。 AvalonEditは、3pxの半径を持つ矩形で背景を描くように見えます。

  • また、AvalonEdit 5.01から始まるRichTextColorizerもあります。他のファイルでは参照されていないので、どのように使用するのかわかりません。そして、前のパラグラフで(最も望ましくない)丸みのある四角形が存在する可能性があります。

+0

私は別のプログラムで年後に戻って、この問題に来て、 'IBackgroundRenderer'を試してみました。描画された矩形が選択矩形よりもわずかに大きかったが、大きな問題ではなかったという事実以外は完全に機能していた。 –

+0

明らかに軽微な問題を修正しただけで、蛍光ペンからペンのブラシを取り外すことは明らかでした。 –

関連する問題