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: &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
PopoverController:
@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
NSScrollView as a descendent view, connected to the
ViewController 's
scrollView`出口。