#objective-c #cocoa #scroll #nspopover
#objective-c #cocoa #прокрутка #nspopover
Вопрос:
Предыстория
Реализация по умолчанию NSPopover
перемещает всплывающее окно, когда оно отображается поверх прокрутки (и имеет специальную обработку для случаев, когда NSRect
оно прикреплено к прокруткам вне поля зрения). NSPopover
Может отображаться поверх NSRulerView
, но NSPopover
не перемещается при прокрутке вида документа (по-видимому, потому, что NSRulerView
не обрабатывает прокрутку, как это делают другие виды, используя смещение чертежа вместо движущегося окна просмотра).
Вопрос
Как можно воссоздать поведение перемещения по умолчанию для объекта, NSPopover
который прикреплен к NSRulerView
?
Пример кода
-
ViewController:
@interface ViewController : NSViewController @property (weak) IBOutlet NSScrollView *scrollView; @property (strong) LineNumberView *ruler; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.ruler = [[LineNumberView alloc] initWithScrollView:self.scrollView orientation:NSVerticalRuler]; self.scrollView.verticalRulerView = self.ruler; self.scrollView.hasVerticalRuler = YES; self.scrollView.rulersVisible = YES; } //... @end
-
LineNumberView Просмотр строки:
@implementation LineNumberView -(void)mouseDown:(NSEvent *)event { [self popOver:[self convertPoint:event.locationInWindow fromView:nil]]; } -(void)popOver:(NSPoint)point { NSRect anchor = [self rectForPoint:point]; PopoverController *pop = [[PopoverController alloc] init]; [pop showOver:anchor ofView:self]; } -(NSRect)rectForPoint:(NSPoint)point { NSTextView* textView = (NSTextView*)self.scrollView.documentView; NSUInteger rectCount; NSRectArray frameRects = [textView.layoutManager rectArrayForCharacterRange: NSMakeRange(NSNotFound, 0) withinSelectedCharacterRange: kNullRange inTextContainer: textView.textContainer rectCount: amp;rectCount ]; const CGFloat kWidth = NSWidth(self.bounds); const CGFloat kHeight = NSHeight(frameRects[0]); const CGFloat x = 0; CGFloat y = point.y - fmod(point.y, kHeight); //y = NSMinY(self.scrollView.contentView.bounds); return NSMakeRect(x, y, kWidth, kHeight); } @end
-
ПоповерКонтроллер:
@interface PopoverController : NSViewController<NSPopoverDelegate> @property (strong) NSPopover *popover; @end @implementation PopoverController -(instancetype)init { if ((self = [super init])) { NSTextField *label = [NSTextField labelWithString:@"Pop!"]; [label setFrameOrigin:NSMakePoint(kPadding, kPadding)]; self.view = [[NSView alloc] initWithFrame:NSMakeRect( 0, 0, 2 * kPadding label.frame.size.width, 2 * kPadding label.frame.size.height)]; [self.view addSubview:label]; self.popover = [[NSPopover alloc] init]; self.popover.contentViewController = self; self.popover.behavior = NSPopoverBehaviorTransient; } return self; } -(void)showOver:(NSRect)anchor ofView:(NSView*)view { [self.popover showRelativeToRect:anchor ofView:view preferredEdge:NSMaxYEdge]; }
-
В основной раскадровке, на выходе
ViewController's scene has an
NSScrollViewas a descendent view, connected to the
ViewController's
ScrollView.