How can I implement row-by-row scrolling in an NSTextView object? It has to work regardless of how the user tries to scroll: either if they drag the scroll knob or use a two-finger scroll gesture on the trackpad. Furthermore, the scroll knob should always move in discrete steps. (This is exactly the way Apples terminal emulator works.)
What I tried to do first was to subclass NSTextView and override adjustScroll: (which it inherits from NSView), which is described here, that is:
- (NSRect)adjustScroll:(NSRect)newVisible {
NSRect modifiedVisible = newVisible;
NSFont *font = [self font];
CGFloat lineHeight = [[self layoutManager] defaultLineHeightForFont:font];
modifiedVisible.origin.x = (int)(modifiedVisible.origin.x/lineHeight) * lineHeight;
modifiedVisible.origin.y = (int)(modifiedVisible.origin.y/lineHeight) * lineHeight;
return modifiedVisible;
}
This however only gives row-by-row scrolling when I use the scroll knob. By accident I found out that subclassing NSScrollView would give me row-by-row scrolling also when scrolling with the trackpad, even though it seems I'm not really doing anything (so why this works is a mystery), the only overridden methods are these:
- (instancetype)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
}
The scroll knob, however, still moves continuously. Do I have to subclass NSScroller and override setDoubleValue (I tried doing that, but it didn't work very well so that solution feels difficult, though maybe possible) or can I override reflectScrolledClipView: in my subclass to NSScrollView (that didn't work at all), or are there better solutions?