AvalonEdit:获取 IBackgroundRenderer 的视觉位置
AvalonEdit: Getting Visual Position for IBackgroundRenderer
在我基于 AvalonEdit 的文档编辑器中,我试图将标记线添加到文本视图以指示文档中的折叠,其方式与 Visual Studio 加入代码块的开始和结束的方式类似带虚线的大括号。
如果文档滚动到最顶部,我有一些东西可以产生正确的结果,但是如果向下滚动文档,它不会正确更新。具体来说,线条的绘制就好像文本视图根本没有滚动一样,并且仍然位于文档的顶部。我怀疑问题与 TextViewPosition
和 GetVisualPosition
行有关,但我不明白如何通过滚动正确获得调整后的视觉位置。
(为了清楚起见,我已经检查过, Draw
方法在适当的时间被调用以更新背景,只是在滚动时不考虑滚动)
到目前为止,我在 class 上实现了以下内容 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 式缩进),因此使用前导空格来查找列。
简而言之,如何从文档行号和列中得到适当调整的视觉位置?
GetVisualPosition
记录为:
Returns: The position in WPF device-independent pixels relative to the top left corner of the document.
要将其用于绘画,您需要从中减去滚动位置:
Point foldStartPos = textView.GetVisualPosition(startViewPos, VisualYPosition.LineBottom);
Point foldEndPos = textView.GetVisualPosition(endViewPos, VisualYPosition.LineBottom);
foldStartPos -= textView.ScrollOffset;
foldEndPos -= textView.ScrollOffset;
至于 TextLocation
与 TextViewPosition
:在某些情况下,有多个可能的位置映射到相同的 TextLocation
。
可能有 VisualLineElement
的自定义 documentLength
为 0。
或者可能启用了自动换行并且在没有 space 字符的位置换行:然后第一个 TextLine
的结尾和第二个 TextLine
的开头都引用到文档中的相同位置。
A TextViewPosition
带有一些额外的信息,可以区分这些情况。这对插入符号非常重要,因此单击某处会将插入符号置于单击的位置;不是另一个同等职位。
在我基于 AvalonEdit 的文档编辑器中,我试图将标记线添加到文本视图以指示文档中的折叠,其方式与 Visual Studio 加入代码块的开始和结束的方式类似带虚线的大括号。
如果文档滚动到最顶部,我有一些东西可以产生正确的结果,但是如果向下滚动文档,它不会正确更新。具体来说,线条的绘制就好像文本视图根本没有滚动一样,并且仍然位于文档的顶部。我怀疑问题与 TextViewPosition
和 GetVisualPosition
行有关,但我不明白如何通过滚动正确获得调整后的视觉位置。
(为了清楚起见,我已经检查过, Draw
方法在适当的时间被调用以更新背景,只是在滚动时不考虑滚动)
到目前为止,我在 class 上实现了以下内容 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 式缩进),因此使用前导空格来查找列。
简而言之,如何从文档行号和列中得到适当调整的视觉位置?
GetVisualPosition
记录为:
Returns: The position in WPF device-independent pixels relative to the top left corner of the document.
要将其用于绘画,您需要从中减去滚动位置:
Point foldStartPos = textView.GetVisualPosition(startViewPos, VisualYPosition.LineBottom);
Point foldEndPos = textView.GetVisualPosition(endViewPos, VisualYPosition.LineBottom);
foldStartPos -= textView.ScrollOffset;
foldEndPos -= textView.ScrollOffset;
至于 TextLocation
与 TextViewPosition
:在某些情况下,有多个可能的位置映射到相同的 TextLocation
。
可能有 VisualLineElement
的自定义 documentLength
为 0。
或者可能启用了自动换行并且在没有 space 字符的位置换行:然后第一个 TextLine
的结尾和第二个 TextLine
的开头都引用到文档中的相同位置。
A TextViewPosition
带有一些额外的信息,可以区分这些情况。这对插入符号非常重要,因此单击某处会将插入符号置于单击的位置;不是另一个同等职位。