在NSTextView中以大写形式呈现一些文本而不更改基础字符串

时间:2015-10-04 04:16:47

标签: macos cocoa nstextview appkit

在NSTextView中,是否可以将字符串的给定范围呈现为全部大写,而无需更改基础字符串本身?这个想法类似于NSLayoutManager's temporary attributesCSS' text-transform property

1 个答案:

答案 0 :(得分:2)

这可能是可能的,但您必须自己实施此类支持。我不相信有任何内置的东西可以做到。

您还必须实现NSLayoutManager的自定义子类和NSGlyphGenerator的自定义子类。您的自定义布局管理器类将具有类似于临时属性接口的接口。这是因为内置临时属性功能不支持修改布局的属性,但更改字符大小写将修改布局。您需要以某种方式存储自定义临时属性并使布局无效。因为您的自定义字形生成器需要它们(见下文),您可能希望将临时属性存储在该对象中。

处理自定义属性将涉及替换不同的字形,因此我认为您需要使用自定义字形生成器。您将自定义子类NSGlyphGenerator的实例传递给布局管理器的glyphGenerator属性的setter。你的字形生成器需要在标准实现和它的字形存储对象(实际上是作为NSGlyphStorage的角色的布局管理器)之间插入它自己。因此,您的子类也将采用NSGlyphStorage协议。

您将覆盖唯一的字形生成器实例方法-generateGlyphsForGlyphStorage:desiredNumberOfCharacters:glyphIndex:characterIndex:。当布局管理器调用您的字形生成器时,您对该方法的覆盖将调用super,但会将self替换为glyphStorage参数。但是,它必须记住实例变量中的原始glyphStorage

然后,超类的实现将调用对象上NSGlyphStorage协议的各种方法。如果您希望您的实现不做任何特殊操作,它只需调用原始的glyphStorage对象。但是,您要检查自定义属性,并且对于它出现的任何运行,请替换大写字母。这必须在-attributedString的实施中发生。您需要制作原始glyphStorage(布局管理器)返回的属性字符串的可变副本,并且对于受自定义临时属性影响的任何范围,请使用这些属性的本地化大写版本替换字符。字符。

您需要对此进行优化,这样您就不会经常复制和修改(可能非常大的)属性字符串,该字符串是布局管理器的文本存储。不幸的是,布局管理器和字形生成器之间相当有限的接口不会使这很容易。文本存储将在布局管理器更改后调用-textStorage:edited:range:changeInLength:invalidatedRange:,因此您可以利用它来使您可能拥有的任何缓存副本无效。