NSTextView 中插入符号下方的 NSPopover

发布于 2024-11-28 06:14:44 字数 293 浏览 1 评论 0原文

我知道为了显示弹出窗口,我需要一个 NSView,但我不认为有一个与插入符号相关联(在 NSTextView 内部)。有没有办法在插入符号下方显示 NSPopover?

我尝试分配 NSView 并使用 (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container 定位它,但弹出窗口不会出现(并且有一个原因,该方法返回 <代码>NSRect: {{0, 0}, {0, 0}})。

I know that in order to show a popover I need an NSView, but I don't think that there is one associated with the caret (inside the NSTextView). Is there a way to show a NSPopover below the caret?

I tried to alloc a NSView and position it using (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container, but the popover will not appear (and there's a reason, that method returns NSRect: {{0, 0}, {0, 0}}).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不醒的梦 2024-12-05 06:14:44

我不确定您是否还在寻找答案。我最近正在开发一个项目,该项目恰好需要像您所描述的非常相似的功能。

您可以在 NSTextView 的子类中执行以下操作:

您要调用的函数是: showRelativeToRect:ofView:preferredEdge:

该矩形将是 NSTextView 内的一个矩形,使用 NSTextView 坐标系,ofView 是 NSTextView,并且PreferredEdge 是您希望此弹出窗口挂钩的边缘。

现在,你说你想让 PopOver 东西显示在插入符号下,那么你必须给他一个 Rect,一个 Point 是不够的。 NSTextView 有一个名为 selectedRange 的选择器,它为您提供所选文本的范围,您可以使用它来定位插入符号。

接下来是调用firstRectForCharacterRange(该类必须委托NSTextInputClient),该方法将返回NSTextView内所选文本的屏幕坐标,然后将它们转换为NSTextView坐标系,您将能够在以下位置显示NSPopover东西正确的立场。这是我执行此操作的代码。

NSRect rect = [self firstRectForCharacterRange:[self selectedRange]]; //screen coordinates

// Convert the NSAdvancedTextView bounds rect to screen coordinates
NSRect textViewBounds = [self convertRectToBase:[self bounds]];
textViewBounds.origin = [[self window] convertBaseToScreen:textViewBounds.origin];

rect.origin.x -= textViewBounds.origin.x;
rect.origin.y -= textViewBounds.origin.y;    
rect.origin.y = textViewBounds.size.height - rect.origin.y - 10; //this 10 is tricky, if without, my control shows a little below the text, which makes it ugly.

NSLog(@"rect %@", NSStringFromRect(rect));
NSLog(@"bounds %@", NSStringFromRect([self bounds]));
if([popover isShown] == false)
    [popover showRelativeToRect:rect
                         ofView:self preferredEdge:NSMaxYEdge];

这就是结果。

我想知道的是,是否有一种方法可以使用系统函数进行转换,虽然我尝试了convertRect:toView,但由于此方法是在委托中编写的,因此 NSTextView 始终具有 (0,0) 坐标系,这使得该方法毫无用处。

NSPopover 显示在所选文本下方

I'm not sure if you are still looking for answer. I recently was working on a project which happens to need a very similar feature like you described.

You can do the following inside a subclass of NSTextView:

the function you are going to call is : showRelativeToRect:ofView:preferredEdge:

the rect will be a rect inside the NSTextView, using the NSTextView coordinate system, the ofView is the NSTextView, and the preferredEdge is the edge you want this popover thing to hook with.

now, you are saying that you want the PopOver thing to show under the caret, well you have to give him a Rect, a Point is not enough. The NSTextView has a selector called selectedRange, which gives you the range of the selected text, you can use that to locate your caret.

the next thing is to call firstRectForCharacterRange (the class must delegate NSTextInputClient), this method will return a screen coordinate of the selected text inside the NSTextView, then you convert them into the NSTextView coordinate system, you will be able to show the NSPopover thing at a correct position. Here's my code of doing this.

NSRect rect = [self firstRectForCharacterRange:[self selectedRange]]; //screen coordinates

// Convert the NSAdvancedTextView bounds rect to screen coordinates
NSRect textViewBounds = [self convertRectToBase:[self bounds]];
textViewBounds.origin = [[self window] convertBaseToScreen:textViewBounds.origin];

rect.origin.x -= textViewBounds.origin.x;
rect.origin.y -= textViewBounds.origin.y;    
rect.origin.y = textViewBounds.size.height - rect.origin.y - 10; //this 10 is tricky, if without, my control shows a little below the text, which makes it ugly.

NSLog(@"rect %@", NSStringFromRect(rect));
NSLog(@"bounds %@", NSStringFromRect([self bounds]));
if([popover isShown] == false)
    [popover showRelativeToRect:rect
                         ofView:self preferredEdge:NSMaxYEdge];

and this is the result.

All the thing I am wondering is that if there is a way to convert using System functions, although I tried the convertRect:toView, but since this method is written in a delegate, the NSTextView always has the coordinate system of (0,0), which makes this method useless.

NSPopover shows underneath the selected text

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文