使用 drawGlyphsForGlyphRange 绘制外部内容插图
Drawing outside content insets with drawGlyphsForGlyphRange
我正在尝试根据文本属性在 NSTextView
中的行旁边显示一些额外的符号。
我已成功子类化 NSLayoutManager
,但布局管理器似乎无法在 textContainerInset
设置的区域之外绘制。
因为我的文本视图可能有很长的字符串,所以我希望保持绘图与显示字形的连接。有没有办法欺骗布局管理器能够在内容插图内绘制——或者我是否使用另一种方法来代替 drawGlyphsForGlyphRange
?
我试过在绘图前后调用 super
,以及存储和不存储图形状态。我也尝试 setDrawsOutsideLineFragment:YES
的字形,但没有运气。
像 Xcode 编辑器本身使用更改标记,所以我知道这在某种程度上是可行的,但很可能我从错误的地方看。
我的画法,简化:
- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(NSPoint)origin {
[super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin];
NSTextStorage *textStorage = self.textStorage;
NSTextContainer *textContainer = self.textContainers[0];
NSRange glyphRange = glyphsToShow;
NSSize offset = self.textContainers.firstObject.textView.textContainerInset;
while (glyphRange.length > 0) {
NSRange charRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL], attributeCharRange, attributeGlyphRange;
id attribute = [textStorage attribute:@"Revision" atIndex:charRange.location longestEffectiveRange:&attributeCharRange inRange:charRange];
attributeGlyphRange = [self glyphRangeForCharacterRange:attributeCharRange actualCharacterRange:NULL];
attributeGlyphRange = NSIntersectionRange(attributeGlyphRange, glyphRange);
if (attribute != nil) {
[NSGraphicsContext saveGraphicsState];
NSRect boundingRect = [self boundingRectForGlyphRange:attributeGlyphRange
inTextContainer:textContainer];
// Find the top of the revision
NSPoint point = NSMakePoint(offset.width - 20, offset.height + boundingRect.origin.y + 1.0);
NSString *marker = @"*";
[marker drawAtPoint:point withAttributes:@{
NSForegroundColorAttributeName: NSColor.blackColor;
}];
[NSGraphicsContext restoreGraphicsState];
}
glyphRange.length = NSMaxRange(glyphRange) - NSMaxRange(attributeGlyphRange);
glyphRange.location = NSMaxRange(attributeGlyphRange);
}
}
答案比我预想的要简单得多。
您可以为关联的 NSTextContainer
设置 lineFragmentPadding
,以便为在边距中绘制留出更多空间。在为文本容器设置插图时必须考虑到这一点。
我正在尝试根据文本属性在 NSTextView
中的行旁边显示一些额外的符号。
我已成功子类化 NSLayoutManager
,但布局管理器似乎无法在 textContainerInset
设置的区域之外绘制。
因为我的文本视图可能有很长的字符串,所以我希望保持绘图与显示字形的连接。有没有办法欺骗布局管理器能够在内容插图内绘制——或者我是否使用另一种方法来代替 drawGlyphsForGlyphRange
?
我试过在绘图前后调用 super
,以及存储和不存储图形状态。我也尝试 setDrawsOutsideLineFragment:YES
的字形,但没有运气。
像 Xcode 编辑器本身使用更改标记,所以我知道这在某种程度上是可行的,但很可能我从错误的地方看。
我的画法,简化:
- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(NSPoint)origin {
[super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin];
NSTextStorage *textStorage = self.textStorage;
NSTextContainer *textContainer = self.textContainers[0];
NSRange glyphRange = glyphsToShow;
NSSize offset = self.textContainers.firstObject.textView.textContainerInset;
while (glyphRange.length > 0) {
NSRange charRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL], attributeCharRange, attributeGlyphRange;
id attribute = [textStorage attribute:@"Revision" atIndex:charRange.location longestEffectiveRange:&attributeCharRange inRange:charRange];
attributeGlyphRange = [self glyphRangeForCharacterRange:attributeCharRange actualCharacterRange:NULL];
attributeGlyphRange = NSIntersectionRange(attributeGlyphRange, glyphRange);
if (attribute != nil) {
[NSGraphicsContext saveGraphicsState];
NSRect boundingRect = [self boundingRectForGlyphRange:attributeGlyphRange
inTextContainer:textContainer];
// Find the top of the revision
NSPoint point = NSMakePoint(offset.width - 20, offset.height + boundingRect.origin.y + 1.0);
NSString *marker = @"*";
[marker drawAtPoint:point withAttributes:@{
NSForegroundColorAttributeName: NSColor.blackColor;
}];
[NSGraphicsContext restoreGraphicsState];
}
glyphRange.length = NSMaxRange(glyphRange) - NSMaxRange(attributeGlyphRange);
glyphRange.location = NSMaxRange(attributeGlyphRange);
}
}
答案比我预想的要简单得多。
您可以为关联的 NSTextContainer
设置 lineFragmentPadding
,以便为在边距中绘制留出更多空间。在为文本容器设置插图时必须考虑到这一点。