AvalonEdit 如何创建缩进引导线?

问题描述 投票:0回答:1

如何在 AvalonEdit 中创建缩进引导线,就像在 Visual Studio 中一样?

c# wpf avalonedit
1个回答
0
投票

我今天才发现这个,没有人回答!我只使用 AvalonEdit 一周左右,并使用以下命令添加了此功能:

应用 IndentGuideLinesRenderer 的代码:

// Create and add the custom background renderer
var indentGuideLinesRenderer = new IndentGuideLinesRenderer(editor);
editor.TextArea.TextView.BackgroundRenderers.Add(indentGuideLinesRenderer);

IndentGuideLinesRenderer 类:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;

public class IndentGuideLinesRenderer : IBackgroundRenderer
{
    private ScrollViewer scrollViewer;
    private TextEditor editor;

    public IndentGuideLinesRenderer(TextEditor editor)
    {
        this.editor = editor;

        scrollViewer = FindVisualChild<ScrollViewer>(editor);
        if (scrollViewer != null)
        {
            // Override the scrolling behavior by handling the ScrollChanged event
            scrollViewer.ScrollChanged += OnScrollChanged;
        }
    }

    public KnownLayer Layer => KnownLayer.Background;

    public void Draw(TextView textView, DrawingContext drawingContext)
    {
        Size pixelSize = PixelSnapHelpers.GetPixelSize(editor);
        textView.EnsureVisualLines();

        foreach (var visualLine in textView.VisualLines)
        {
            var line = editor.Document.GetLineByNumber(visualLine.FirstDocumentLine.LineNumber);
            var text = editor.Document.GetText(line);
            var indentation = 0;

            foreach (var c in text)
            {
                // Check for spaces before text
                if (c == ' ')
                    indentation++;
                else
                    break;

                // Draw the indent guide lines only for every second indentation
                if (indentation >= 4 && (indentation - 4) % 4 == 0) // Adjust 4 to the desired indentation level
                {
                    var startX = textView.GetVisualPosition(new TextViewPosition(line.LineNumber, indentation), VisualYPosition.TextTop).X - 5;
                    var startY = visualLine.GetTextLineVisualYPosition(visualLine.TextLines[0], VisualYPosition.LineTop) - editor.VerticalOffset;
                    var endY = visualLine.GetTextLineVisualYPosition(visualLine.TextLines[0], VisualYPosition.LineBottom) - editor.VerticalOffset;

                    // Create a dotted Pen
                    Pen dottedPen = new Pen(Brushes.LightGray, 1)
                    {
                        DashStyle = DashStyles.Dot, // or DashStyles.Dash for a dashed line
                        StartLineCap = PenLineCap.Square,
                        EndLineCap = PenLineCap.Square,
                        LineJoin = PenLineJoin.Miter
                    };

                    // Draw the indent guide line
                    if (IsDivisibleByMultipleOf(indentation, 8))
                        drawingContext.DrawLine(dottedPen, new System.Windows.Point(startX - pixelSize.Width / 2, startY + pixelSize.Height / 2), new System.Windows.Point(startX - pixelSize.Width / 2, endY + pixelSize.Height / 2));
                    else
                        drawingContext.DrawLine(dottedPen, new System.Windows.Point(startX, startY), new System.Windows.Point(startX, endY));
                }
            }
        }
    }

    // Helper method to find a child of a specified type in the visual tree
    private T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            if (child is T typedChild)
            {
                return typedChild;
            }
            else
            {
                T childOfChild = FindVisualChild<T>(child);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
        }
        return null;
    }

    // Function to check if a number is divisible by a multiple of another number
    private bool IsDivisibleByMultipleOf(int number, int multiple)
    {
        return number % multiple == 0;
    }

    private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        // Calls the InvalidateVisual method to refresh the vertical guide lines on scroll
        editor.TextArea.TextView.InvalidateVisual();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.