Avalon 中的大写编辑

Hus*_*lil 3 c# wpf avalonedit

我正在使用 AvalonEdit 编写电影脚本编辑器。

我扩展了 DocumentLine 类以具有“Type”属性,其值表示“字符”、“对话行”等。

我希望脚本中某种类型的文档行以大写形式编写(例如字符名称)。

渲染管道中是否有一个扩展点可以让我获取文档行并更改其大小写?

我尝试创建一个扩展 DocumentColorizingTransformer 的类,但是更改“protected override void ColorizeLine(DocumentLine line)”方法中的大小写不起作用。

Dan*_*iel 5

这很困难,因为大写可以改变显示字符和文档之间的映射(视觉列与文档偏移量)。

\n\n

例如,单个字符 \'\xc3\x9f\'(德语升号 s)仅以小写字母形式存在,并在调用时转换为两个字符的字符串“SS” string.ToUpper()。\n编辑此文本很棘手:我们不能允许用户仅替换其中一个“S”,因为底层文档仅包含“\xc3\x9f”。

\n\n

一个简单的解决方案是改用该char.ToUpper()方法,在原始字符和大写字符之间强制执行一对一映射。这将使像“\'\xc3\x9f\”这样的字母保持不变。

\n\n

在 AvalonEdit 4.2 中,仅允许对已生成的 VisualLineElements 进行两种转换:

\n\n
    \n
  • 更改文本运行属性,例如字体大小、文本颜色等。
  • \n
  • 将 VisualLineElement 一分为二 - 这是内部使用的,ChangeLinePart()以便可以更改文本部分的属性。
  • \n
\n\n

这意味着无法在着色器中进行文本替换,您需要使用VisualLineElementGenerator.

\n\n
/// <summary>\n/// Makes all text after a colon (until the end of line) upper-case.\n/// </summary>\npublic class UppercaseGenerator : VisualLineElementGenerator\n{\n    public override int GetFirstInterestedOffset(int startOffset)\n    {\n        TextDocument document = CurrentContext.Document;\n        int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;\n        for (int i = startOffset; i < endOffset; i++) {\n            char c = document.GetCharAt(i);\n            if (c == \':\')\n                return i + 1;\n        }\n        return -1;\n    }\n\n    public override VisualLineElement ConstructElement(int offset)\n    {\n        DocumentLine line = CurrentContext.Document.GetLineByOffset(offset);\n        return new UppercaseText(CurrentContext.VisualLine, line.EndOffset - offset);\n    }\n\n    /// <summary>\n    /// Displays a portion of the document text, but upper-cased.\n    /// </summary>\n    class UppercaseText : VisualLineText\n    {\n        public UppercaseText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length)\n        {\n        }\n\n        protected override VisualLineText CreateInstance(int length)\n        {\n            return new UppercaseText(ParentVisualLine, length);\n        }\n\n        public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context)\n        {\n            if (context == null)\n                throw new ArgumentNullException("context");\n\n            int relativeOffset = startVisualColumn - VisualColumn;\n            StringSegment text = context.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset + relativeOffset, DocumentLength - relativeOffset);\n            char[] uppercase = new char[text.Count];\n            for (int i = 0; i < text.Count; i++) {\n                uppercase[i] = char.ToUpper(text.Text[text.Offset + i]);\n            }\n            return new TextCharacters(uppercase, 0, uppercase.Length, this.TextRunProperties);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 AvalonEdit 4.3.0.8868 中,我添加了方法VisualLine.ReplaceElement()。这可用于将默认VisualText元素替换为UppercaseText行变换器(着色器)中的元素。

\n\n

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

\n\n
\n\n

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

\n\n
// in the colorizer:\nChangeLinePart(start, end, e => e.TextRunProperties.SetTypographyProperties(new CapsTypography()));\n\n// helper class\nclass CapsTypography : DefaultTextRunTypographyProperties\n{\n    public override FontCapitals Capitals {\n        get { return FontCapitals.SmallCaps; }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,仅当使用支持小型大写字母的 OpenType 字体时,WPF 才会呈现小型大写字母。在我的测试中,Cambria使用小型大写字母,大多数其他字体不使用。\n此外,该SetTypographyProperties方法和DefaultTextRunTypographyProperties类需要 AvalonEdit 4.3。

\n