2012-07-14 82 views
2

我正在使用AvalonEdit编写一个电影脚本编辑器。AvalonEdit中的大写

我延长DocumentLine类具有“类型”属性,与代表值或者是“字符”,“对话行”等

我想在脚本内的特定类型的文件系以大写字母(例如字符名称)写入。

有没有渲染管线内的扩展点,让我去取文件行并把它的外壳?

我试图创建一个扩展DocumentColorizingTransformer一类,但改变内壳“保护覆盖无效ColorizeLine(DocumentLine线)”的方法没有奏效。

回答

4

这是困难的,因为上部壳体可以改变所显示的字符和这个文档(视觉列与文件偏移量)之间的映射。

例如,单个字符'ß'(德语sharp s)只能作为小写字母存在,并在调用string.ToUpper()时转换为双字符字符串“SS”。 编辑这个文本是棘手的:我们不能让用户只替换其中的一个'S',因为底层文档只包含'ß'。

一个简单的解决方案是使用所述char.ToUpper()方法来代替,执行原始和大写字符之间的一对一的映射。这将保持字母'ß'不变。

在AvalonEdit 4.2,只有两个转变被允许在已产生VisualLineElements:

  • 更改文本运行特性,例如字体大小,文本颜色等
  • 拆分一VisualLineElement两个 - 这是内部由ChangeLinePart()如此使用该属性可以用于文本部分被改变。

这意味着无法在着色器中进行文本替换,您需要使用VisualLineElementGenerator执行此操作。

/// <summary> 
/// Makes all text after a colon (until the end of line) upper-case. 
/// </summary> 
public class UppercaseGenerator : VisualLineElementGenerator 
{ 
    public override int GetFirstInterestedOffset(int startOffset) 
    { 
     TextDocument document = CurrentContext.Document; 
     int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset; 
     for (int i = startOffset; i < endOffset; i++) { 
      char c = document.GetCharAt(i); 
      if (c == ':') 
       return i + 1; 
     } 
     return -1; 
    } 

    public override VisualLineElement ConstructElement(int offset) 
    { 
     DocumentLine line = CurrentContext.Document.GetLineByOffset(offset); 
     return new UppercaseText(CurrentContext.VisualLine, line.EndOffset - offset); 
    } 

    /// <summary> 
    /// Displays a portion of the document text, but upper-cased. 
    /// </summary> 
    class UppercaseText : VisualLineText 
    { 
     public UppercaseText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length) 
     { 
     } 

     protected override VisualLineText CreateInstance(int length) 
     { 
      return new UppercaseText(ParentVisualLine, length); 
     } 

     public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context) 
     { 
      if (context == null) 
       throw new ArgumentNullException("context"); 

      int relativeOffset = startVisualColumn - VisualColumn; 
      StringSegment text = context.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset + relativeOffset, DocumentLength - relativeOffset); 
      char[] uppercase = new char[text.Count]; 
      for (int i = 0; i < text.Count; i++) { 
       uppercase[i] = char.ToUpper(text.Text[text.Offset + i]); 
      } 
      return new TextCharacters(uppercase, 0, uppercase.Length, this.TextRunProperties); 
     } 
    } 
} 

在AvalonEdit 4.3.0.8868,我添加的方法VisualLine.ReplaceElement()。这可以用于在线路变压器(变色器)内用UppercaseText元件替换默认的VisualText元件。

注意的是,还可以实现为“SS”支持被显示为“SS”。为此,您必须实施自己的VisualLineText副本,而不是仅仅覆盖现有副本。然后,您可以使用与文档长度不同的可视长度。将使用GetRelativeOffsetGetVisualColumns方法来提供文档和视觉坐标之间的映射。


您还可以使用另一个选项:小型大写字母。

// in the colorizer: 
ChangeLinePart(start, end, e => e.TextRunProperties.SetTypographyProperties(new CapsTypography())); 

// helper class 
class CapsTypography : DefaultTextRunTypographyProperties 
{ 
    public override FontCapitals Capitals { 
     get { return FontCapitals.SmallCaps; } 
    } 
} 

但是,只有在使用支持它们的OpenType字体时,WPF才会呈现小型大写字母。在我的测试中,Cambria使用小型大写字母,其他大多数字体都没有。 此外,SetTypographyProperties方法和DefaultTextRunTypographyProperties类需要AvalonEdit 4.3。

+0

谢谢你这么详细的回答,我真的很感激。你总是很有帮助。 :) – 2012-07-19 19:51:39