【问题标题】:AvalonEdit: Getting Visual Position for IBackgroundRendererAvalonEdit:获取 IBackgroundRenderer 的视觉位置
【发布时间】:2020-07-21 20:50:28
【问题描述】:

在我的基于 AvalonEdit 的文档编辑器中,我尝试将标记线添加到文本视图以指示文档中的折叠,其方式类似于 Visual Studio 如何使用虚线连接代码块大括号的开头和结尾。

如果文档滚动到最顶部,我有一些东西会产生正确的结果,但如果文档向下滚动,它不会正确更新。具体来说,线条的绘制就好像文本视图根本没有滚动一样,并且仍然位于文档的顶部。我怀疑这个问题与TextViewPositionGetVisualPosition 行有关,但我不明白如何通过滚动正确获得调整后的视觉位置。

(需要明确的是,我已经检查过了,Draw 方法会在适当的时候被调用来更新背景,只是滚动时没有考虑到)

到目前为止,我在一个实现 IBackgroundRenderer 的类上拥有以下内容:

public void Draw(TextView textView, DrawingContext drawingContext) {
    if (textView == null) { throw new ArgumentNullException("textView"); }
    if (drawingContext == null) { throw new ArgumentNullException("drawingContext"); }
    if (!textView.VisualLinesValid) { return; }
    ReadOnlyCollection<VisualLine> visualLines = textView.VisualLines;
    if (visualLines.Count == 0) { return; }

    foreach (FoldingSection fold in foldingManager.AllFoldings.Where(f => !f.IsFolded)) {

        DocumentLine startLine = textView.Document.GetLineByOffset(fold.StartOffset);
        ISegment whitespace = TextUtilities.GetLeadingWhitespace(textView.Document, startLine);
        if(whitespace.Length == 0) { continue; }
        DocumentLine endLine = textView.Document.GetLineByOffset(fold.EndOffset);

        TextLocation foldStart = textView.Document.GetLocation(whitespace.EndOffset);
        TextLocation foldEnd = textView.Document.GetLocation(textView.Document.GetOffset(endLine.LineNumber, foldStart.Column));

        // I am unsure exactly what TextViewPosition is meant to represent, in contrast to TextLocation
        TextViewPosition startViewPos = new TextViewPosition(foldStart);
        TextViewPosition endViewPos = new TextViewPosition(foldEnd);

        // These lines are definitely not returning what I expect
        Point foldStartPos = textView.GetVisualPosition(startViewPos, VisualYPosition.LineBottom);
        Point foldEndPos = textView.GetVisualPosition(endViewPos, VisualYPosition.LineBottom);

        Brush brush = new SolidColorBrush(LineColor);
        brush.Freeze();
        Pen dashPen = new Pen(brush, 0.5) { DashStyle = new DashStyle(new double[] { 2, 2 }, 0) };
        dashPen.Freeze();
        // New point created to avoid issues with nested folds causing slanted lines
        drawingContext.DrawLine(dashPen, foldStartPos, new Point(foldStartPos.X, foldEndPos.Y));
    }
}

文档的折叠基于空格(非常类似于 Python 样式的缩进),因此使用前导空格来查找列。

简而言之,如何从文档的行号和列中获得适当调整的视觉位置?

【问题讨论】:

    标签: c# wpf avalonedit


    【解决方案1】:

    GetVisualPosition 记录为:

    返回:WPF 设备无关像素相对于文档左上角的位置。

    要将其用于绘画,您需要从中减去滚动位置:

    Point foldStartPos = textView.GetVisualPosition(startViewPos, VisualYPosition.LineBottom);
    Point foldEndPos = textView.GetVisualPosition(endViewPos, VisualYPosition.LineBottom);
    foldStartPos -= textView.ScrollOffset;
    foldEndPos -= textView.ScrollOffset;
    

    至于TextLocationTextViewPosition:在某些情况下,有多个可能的位置映射到同一个TextLocation。 可能有自定义的VisualLineElements,documentLength 为 0。 或者可能启用了自动换行,并且在没有空格字符的位置换行:那么第一个 TextLine 的结尾和第二个 TextLine 的开头都指向文档中的相同位置。

    TextViewPosition 带有一些额外的信息,可以区分这些情况。这对于插入符号非常重要,因此单击某处会将插入符号置于单击位置;不是另一个同等职位。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      • 2016-02-20
      相关资源
      最近更新 更多