簡體   English   中英

AvalonEdit顯示選擇其他格式

[英]AvalonEdit show selection over other formatting

我目前正在使用以下代碼作為AvalonEdit TextEditorLineTransformer 我希望能夠通過選擇突出顯示當前的單個搜索結果,但是該選擇幾乎不可見,因為DocumentColorizingTransformer的格式優先於顯示突出顯示的文本。 如何顯示突出顯示的選擇內容而不是顯示格式?

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++;
        }
    }
}

顯示過度選擇的格式示例

有關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));

在廣泛嘗試了解決方案之后,我想補充幾點:

  • 盡管上面的其他解決方案似乎可行,但是當應該將矩形平鋪時,會有一些亞像素偽像。 如果不可接受,則可以實現IBackgroundRenderer。 (這恰好是我選擇的解決方案。)如果您想要一些代碼,可以在這里請求,但是我懷疑它是否有用。

  • 順便說一句, 由於您的問題是關於搜索結果的因此最有可能使用未經修改的https://github.com/icsharpcode/AvalonEdit/blob/697ff0d38c95c9e5a536fbc05ae2307ec9ef2a63/ICSharpCode.AvalonEdit/Search/Search/SearchResultBackgroundRenderer.cs (如果您不進行修改,則可以對其進行修改)想要圓角邊框)。

  • 您可以使用element.BackgroundBrush = Brushes.Magenta; 而不是element.TextRunProperties.SetBackgroundBrush(Brushes.Magenta); AvalonEdit似乎使用3px半徑的矩形繪制背景。

  • 從AvalonEdit 5.01開始還有RichTextColorizer。 我不知道如何使用它,因為在其他文件中未引用它。 並且上一段中(最可能不需要的)圓角矩形很可能會出現。

因此,這是我的最終產品,幾乎完全基於現有的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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM