【问题标题】:NSLayoutManager glyph generation and caret positionNSLayoutManager 字形生成和插入符号位置
【发布时间】:2023-04-08 17:56:01
【问题描述】:

我有一个文本编辑器应用程序,它使用 Markdown 样式格式。当插入符号/选择不在相应的行上时,格式字符被隐藏。

我成功地使用NSLayoutManagerDelegate 中的shouldGenerateGlyphs: 方法来操纵NSTextView 上绘制的内容。我使用的是纯委托,并且没有子类化布局管理器本身。

但是,我不明白如何在字形重新生成后正确定位插入符号。选择更改后,我正在调用一个方法(这里称为hideAndShowMarkup),它为当前编辑的行和之前选择的行重新生成字形。由于在屏幕上添加了一些字形,插入符号的渲染错误。

-(void)hideAndShowMarkup {
    [self.layoutManager invalidateGlyphsForCharacterRange:currentLine.range changeInLength:0 actualCharacterRange:nil];
    [self.layoutManager invalidateGlyphsForCharacterRange:prevLine.range changeInLength:0 actualCharacterRange:nil];
    
    [self.layoutManager ensureGlyphsForCharacterRange:currentLine.range];
    [self.layoutManager ensureGlyphsForCharacterRange:prevLine.range];

    [self updateInsertionPointStateAndRestartTimer:YES];
}

updateInsertionPoint... 在这里不起作用,因为确保字形似乎异步运行。我也试过在didCompleteLayoutForTextContainer:委托方法中调用它,但没有效果。

有没有办法检测字形何时被实际绘制,并在此之后确保插入点的位置?

【问题讨论】:

  • 不应该需要invalidateGlyphsForCharacterRangeensureGlyphsForCharacterRange 之一。请张贴minimal reproducible example
  • 我通过浏览随机的 GitHub 存储库找到了一个解决方案,并将发布我的发现,因为有多个问题涉及相同的主题。

标签: objective-c macos cocoa appkit nstextview


【解决方案1】:

NSLayoutManager 的文档记录出奇地差,要了解其内部工作原理,需要查看随机公共存储库中的实现。

要更改范围内的字形并正确设置插入符号的位置,您首先需要使两个已更改范围的字形无效,然后使插入符号即将成为的范围的布局无效定位在。

然后,在确保存在当前图形上下文后,可以同步重绘字形。之后,更新插入点就可以正常工作了。

在下面的示例中,我有两个对象,lineprevLine,它们包含插入符号现在所在的行和一个插入符号离开的行的范围。

-(void)hideAndShowMarkup {
    [self.layoutManager invalidateGlyphsForCharacterRange:line.range changeInLength:0 actualCharacterRange:nil];
    [self.layoutManager invalidateGlyphsForCharacterRange:prevLine.range changeInLength:0 actualCharacterRange:nil];
    [self.layoutManager invalidateLayoutForCharacterRange:line.range actualCharacterRange:nil];
        
    if (NSGraphicsContext.currentContext) {
        [self.layoutManager drawGlyphsForGlyphRange:line.range atPoint:self.frame.origin];
        [self.layoutManager drawGlyphsForGlyphRange:prevLine.range atPoint:self.frame.origin];
    }
    
    [self updateInsertionPointStateAndRestartTimer:NO];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多