NSPopover ниже каретки в NSTextView - PullRequest
3 голосов
/ 05 августа 2011

Я знаю, что для показа всплывающего окна мне нужен NSView, но я не думаю, что есть один, связанный с кареткой (внутри NSTextView). Есть ли способ показать NSPopover ниже каретки?

Я попытался выделить NSView и позиционировать его, используя (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container, но всплывающее окно не появится (и есть причина, что метод возвращает NSRect: {{0, 0}, {0, 0}}).

1 Ответ

10 голосов
/ 26 декабря 2011

Я не уверен, что вы все еще ищете ответ.Недавно я работал над проектом, который нуждается в очень похожей функции, как вы описали.

Внутри подкласса NSTextView вы можете сделать следующее:

функция, которую вы собираетесь вызвать,: showRelativeToRect: ofView: предпочитаемый край:

прямоугольник будет прямоугольником внутри NSTextView, используя систему координат NSTextView, ofView - это NSTextView, а предпочитаемый край - это край, с которым вы хотите, чтобы эта попсовая вещь была подключена.

Теперь вы говорите, что хотите, чтобы вещь PopOver показывалась под кареткой, ну, вы должны дать ему Рект, Очка недостаточно.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 shows underneath the selected text

...