Discrete (row-by-row) scrolling in NSTextView

166 Views Asked by At

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?

0

There are 0 best solutions below