2012-08-30 81 views
3

我正在编写使用avalon编辑的自定义软件,并且正在寻找一种使行间空间(高度)更大的方法。目前,我不得不在每次用户写完一行并想写另一行时添加一行空行。更改avalon中的默认行高编辑

我已经开始调查TextView类,其中defaultLineHeight似乎被计算出来,但我能够影响的唯一的事情是视觉符号的高度,而不是内容本身。

目前,我正在寻找使每一对隐形线,但我希望有一个更简单的方法来实现在线之间添加更多空间的简单操作。

以下是来自TextView类的方法我正在检查此刻。任何提示或提示将受到欢迎。

void CalculateDefaultTextMetrics() 
{ 
    if (defaultTextMetricsValid) 
    { 
     return; 
    } 

    defaultTextMetricsValid = true; 
    if (formatter != null) 
    { 
     var textRunProperties = CreateGlobalTextRunProperties(); 
     using (
      var line = formatter.FormatLine(
       new SimpleTextSource("x", textRunProperties), 
       0, 
       32000, 
       new VisualLineTextParagraphProperties { defaultTextRunProperties = textRunProperties }, 
       null)) 
     { 
      wideSpaceWidth = Math.Max(1, line.WidthIncludingTrailingWhitespace); 
      defaultBaseline = Math.Max(1, line.Baseline); 
      defaultLineHeight = Math.Max(1, line.Height); 
     } 
    } 
    else 
    { 
     wideSpaceWidth = FontSize/2; 
     defaultBaseline = FontSize; 
     **defaultLineHeight = FontSize + 3; // bigger value only affects caret height :(** 
    } 

    // Update heightTree.DefaultLineHeight, if a document is loaded. 
    if (heightTree != null) 
    { 
     heightTree.DefaultLineHeight = defaultLineHeight; 
    } 
} 

由于

回答

5

DefaultLineHeight处于默认字体的线,这是用作用于每一行的高度的初始假设的高度。 (例如,用于计算滚动条位置)

每当实际测量一条线(TextView.BuildVisualLine)时,测量的高度将存储在高度树中,覆盖默认高度。这是因为换行(或换行符改变字体大小)会导致每一行的高度不同。

目前不支持行间距。如果您想补充一点,您可以尝试更改VisualLine的高度计算,例如通过更改VisualLine.SetTextLines()

1

我知道这是一个旧帖子,但我刚刚遇到了这个问题。我设法添加符合以下修改间距很容易:

  1. 添加新double依赖属性TextView称为LineSpacing1.0
  2. VisualLine.SetTextLines默认值,由textView.LineSpacing
  3. line.HeightVisualLine.GetTextLineVisualYPositionVisualLine.GetTextLineByVisualYPosition,乘以tl.Height各出现textView.LineSpacing

然后您可以直接在代码中或通过自定义XAML样式等设置TextView.LineSpacing

这似乎是所有必需的。

PS - AvalonEdit太棒了!

1

包括@Peter Moore说的。为了强制文本正确呈现,还需要执行一个步骤。

VisualLine.cs的底部是类,它负责绘制实际文字,但无权访问TextView类。

修改构造函数以包含double lineSpacing作为参数,并将textLine.Height的所有实例乘以lineSpacing

VisualLine.Render()中,通过textView.LineSpacing作为VisualLineDrawingVisual的现在修改的构造函数的辅助参数。在这之后,所有东西都应该绘制正确

这里的修改后的代码的完整视图:

TextView.cs

public static readonly DependencyProperty LineSpacingProperty = 
    DependencyProperty.Register("LineSpacing", typeof(double), typeof(TextView), 
           new FrameworkPropertyMetadata(1.0)); 

public double LineSpacing { 
    get { return (double) GetValue(LineSpacingProperty); } 
    set { SetValue(LineSpacingProperty, value); } 
} 

VisualLine.cs

线269

internal void SetTextLines(List<TextLine> textLines) { 
    this.textLines = textLines.AsReadOnly(); 
    Height = 0; 
    foreach (TextLine line in textLines) 
     Height += line.Height * textView.LineSpacing; 
} 

线335

public double GetTextLineVisualYPosition(TextLine textLine, VisualYPosition yPositionMode) { 
    if (textLine == null) 
     throw new ArgumentNullException("textLine"); 
    double pos = VisualTop; 
    foreach (TextLine tl in TextLines) { 
     if (tl == textLine) { 
      switch (yPositionMode) { 
      case VisualYPosition.LineTop: 
       return pos; 
      case VisualYPosition.LineMiddle: 
       return pos + tl.Height/2 * textView.LineSpacing; 
      case VisualYPosition.LineBottom: 
       return pos + tl.Height * textView.LineSpacing; 
      case VisualYPosition.TextTop: 
       return pos + tl.Baseline - textView.DefaultBaseline; 
      case VisualYPosition.TextBottom: 
       return pos + tl.Baseline - textView.DefaultBaseline + textView.DefaultLineHeight; 
      case VisualYPosition.TextMiddle: 
       return pos + tl.Baseline - textView.DefaultBaseline + textView.DefaultLineHeight/2; 
      case VisualYPosition.Baseline: 
       return pos + tl.Baseline; 
      default: 
       throw new ArgumentException("Invalid yPositionMode:" + yPositionMode); 
      } 
     } 
     else { 
      pos += tl.Height * textView.LineSpacing; 
     } 
    } 
    throw new ArgumentException("textLine is not a line in this VisualLine"); 
} 

线386

public TextLine GetTextLineByVisualYPosition(double visualTop) { 
    const double epsilon = 0.0001; 
    double pos = this.VisualTop; 
    foreach (TextLine tl in TextLines) { 
     pos += tl.Height * textView.LineSpacing; 
     if (visualTop + epsilon < pos) 
      return tl; 
    } 
    return TextLines[TextLines.Count - 1]; 
} 

线701

internal VisualLineDrawingVisual Render() { 
    Debug.Assert(phase == LifetimePhase.Live); 
    if (visual == null) 
     visual = new VisualLineDrawingVisual(this, textView.LineSpacing); 
    return visual; 
} 

714线

public VisualLineDrawingVisual(VisualLine visualLine, double lineSpacing) { 
    this.VisualLine = visualLine; 
    var drawingContext = RenderOpen(); 
    double pos = 0; 
    foreach (TextLine textLine in visualLine.TextLines) { 
     textLine.Draw(drawingContext, new Point(0, pos), InvertAxes.None); 
     pos += textLine.Height * lineSpacing; 
    } 
    this.Height = pos; 
    drawingContext.Close(); 
} 
0

除了@罗伯特乔丹所说的,还有一些我必须做的更改才能获得满意的结果。

首先,以使文本标记覆盖以覆盖线的整个高度,改变BackgroundGeometryBuilder.cs以下行

ProcessTextLines法,线196:

215行:

yield return new Rect(pos, y, 1, line.Height * textView.LineSpacing); 

行259:

lastRect = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height * textView.LineSpacing); 

行259:

Rect extendSelection = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height * textView.LineSpacing); 

第二个问题我有是,案文在现在延长线高度的顶部,而不是底部呈现。为了解决这个问题,需要在渲染行之前添加额外的空间,而不是之后。所以,做如下修改:

VisualLine.cs,714线

public VisualLineDrawingVisual(VisualLine visualLine, double lineSpacing) { 
    this.VisualLine = visualLine; 
    var drawingContext = RenderOpen(); 
    double pos = 0; 
    foreach (TextLine textLine in visualLine.TextLines) { 
     pos +=(textLine.Height * lineSpacing)-textLine.Height 
     textLine.Draw(drawingContext, new Point(0, pos), InvertAxes.None); 
     pos += textLine.Height; 
    } 
    this.Height = pos; 
    drawingContext.Close(); 
} 

另外,我发现它微不足道的将其转换为支持动态线逐线线间距。只要将LineSpacing属性VisualLine,然后添加一个VisualLineTransformer这样的:

class LinePaddingTransformer : IVisualLineTransformer 
{ 
    public LinePaddingTransformer() 
    { 
     _clientLines = clientLines; 
    } 
    public void Transform(ITextRunConstructionContext context, IList<VisualLineElement> elements) 
    { 
     int index = context.VisualLine.FirstDocumentLine.LineNumber - 1; 
     //You need to calculate your padding from the line index somehow. 
     //for example create a list of objects with the spacing in them and pass to this transformer. 
     double spacing= GetLinePaddingMethod(index); 
     context.VisualLine.LineSpacing= spacing; 
    } 
} 

如果您需要只被添加到第一行文字环绕的情况下的间距,你需要去对你的每一个地方先前乘以LineSpacing属性,并检查TextLine是否为集合中的第一行。