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

我扩展了DocumentLine类,使其具有“ Type”属性,该值表示“ Character”,“ Dialog Line”等。

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

渲染管道中是否存在扩展点,该扩展点将允许我获取文档行并更改其大小写?

我尝试创建一个扩展DocumentColorizingTransformer的类,但是在“受保护的重写void ColorizeLine(DocumentLine行)”方法中更改大小写不起作用。

最佳答案

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

例如,单个字符“ß”(德语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()。这可用于将线性转换器(着色器)中的默认VisualText元素替换为UppercaseText元素。

注意,也可以实现对将“ß”显示为“ 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; }
    }
}


但是,WPF仅在使用支持大写字母的OpenType字体时才渲染小写字母。在我的测试中,Cambria使用小写字母,而其他大多数字体则不能。
此外,SetTypographyProperties方法和DefaultTextRunTypographyProperties类需要AvalonEdit 4.3。

关于c# - AvalonEdit中的大写,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11487234/

10-11 00:59