7

我正在使用 NSTextView,我的要求之一是制表符“\ t”的宽度应与四个空格相同。

所以文本内容看起来像这样:

AAAA
    AAAA - 1 tab
    AAAA - 4 spaces

这就是我如何做到这一点:

// done when NSTextView first loaded and when
// delegate's textDidBeginEditing gets called: (perhaps overkill, but is a work in progress).
- (void)updateMyTextViewTextAttributes
{
    NSMutableParagraphStyle* paragraphStyle = [[myTextView defaultParagraphStyle] mutableCopy];
    if (paragraphStyle == nil) {
        paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    }
    float charWidth = [[myFont screenFontWithRenderingMode:NSFontDefaultRenderingMode] advancementForGlyph:(NSGlyph) ' '].width;
    [paragraphStyle setDefaultTabInterval:(charWidth * 4)];
    [paragraphStyle setTabStops:[NSArray array]];
    [myTextView setDefaultParagraphStyle:paragraphStyle];

    NSMutableDictionary* typingAttributes = [[myTextView typingAttributes] mutableCopy];
    [typingAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
    [typingAttributes setObject:scriptFont forKey:NSFontAttributeName];
    [myTextView setTypingAttributes:typingAttributes];
}

这允许适当的布局与初始文本一起显示,并保持输入属性相同。

问题是最终用户可以更改字体。发生这种情况时,示例文本会错位。很像下面的:

[smaller font]
AAAA
     AAAA - 1 tab
    AAAA - 4 spaces


[larger font]
AAAA
   AAAA - 1 tab
    AAAA - 4 spaces

我已经尝试调用 myTextView 的 setNeedsDisplay:YES,因为我读到它最终调用了 NSTextView 的 setNeedsDisplayInRect:avoidAdditionalLayout,并且对于 AvoidAdditionalLayout 参数使用了 NO。这并没有改变什么。

当 myTextView 设置了新的 myFont 时,我尝试调用我的 updateMyTextViewTextAttributes 调用。这不会改变任何事情。

我还尝试告诉 myTextView 的 layoutManager 为 myTextView 的 textContainer 确保LayoutForTextContainer。不用找了。

在这一点上,我不确定下一步该尝试什么。有什么建议么?

4

2 回答 2

4

Apple 的 Douglas Davidson 为我提供了通过 cocoa-dev@apple.lists.com 电子邮件列表获得答案的线索。

我已经通过更新 updateMyTextViewTextAttributes 函数解决了这个问题,如下所示:

- (void)updateMyTextViewTextAttributes
{
   NSMutableParagraphStyle* paragraphStyle = [[myTextView defaultParagraphStyle] mutableCopy];

   if (paragraphStyle == nil) {
       paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
   }

   float charWidth = [[myFont screenFontWithRenderingMode:NSFontDefaultRenderingMode] advancementForGlyph:(NSGlyph) ' '].width;
   [paragraphStyle setDefaultTabInterval:(charWidth * 4)];
   [paragraphStyle setTabStops:[NSArray array]];

   [myTextView setDefaultParagraphStyle:paragraphStyle];

   NSMutableDictionary* typingAttributes = [[myTextView typingAttributes] mutableCopy];
   [typingAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
   [typingAttributes setObject:scriptFont forKey:NSFontAttributeName];
   [myTextView setTypingAttributes:typingAttributes];

   /** ADDED CODE BELOW **/
   NSRange rangeOfChange = NSMakeRange(0, [[myTextView string] length]);
   [myTextView shouldChangeTextInRange:rangeOfChange replacementString:nil];
   [[myTextView textStorage] setAttributes:typingAttributes range:rangeOfChange];
   [myTextView didChangeText];

   [paragraphStyle release];
   [typingAttributes release];
}
于 2010-02-19T18:16:46.887 回答
1

您是否尝试过advancementForGlyph:直接在字体而不是屏幕字体上计算空间前进?

float charWidth = [myFont advancementForGlyph:(NSGlyph) ' '].width;

屏幕字体不打算直接在窗口服务器之外使用:

屏幕字体仅供窗口服务器直接使用。切勿将它们与 Application Kit 对象一起使用,例如在 setFont: 方法中。在内部,只要视图没有旋转或缩放,Application Kit 就会自动为字体对象使用相应的屏幕字体。

于 2010-02-18T08:29:54.727 回答