Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pinning NSScrollView's document view while resizing a window

This seems like such a trivial question to ask, but it's been vexing me for a while.

I have a window which contains a scroll view. Typically, the scroll view has a documentView that is vertically larger than the clip view, so you get a vertical scroller to see all the content inside the scroll view.

When I resize the window, I recalculate the size of the content in the scroll view's documentView (because the scroll view can get thinner, which might make it necessary for the documentView to grow in height). A side effect, however, is that when resizing the window, the documentView keeps the bottom visible edge flush with the bottom edge of the clip view (that is, it makes sure that the last line of text is always visible). This is a weird effect, because typically, windows keep the top visible edge of the document view flush with the top edge of the clip view (that is, the topmost line of text in the document view remains pinned to the top).

So, my initial thought to fix this problem was just to implement a windowDidResize: or windowWillResize:toSize: notification, note the delta between the old window frame's height and the new height, and then simply scroll the scroll view that much in order to keep the top line of the scroll view pinned to the top.

However, for some reason, this doesn't seem to work. It almost works, but some resizing deltas seem to be a pixel off, and if you resize the window fast enough, it sometimes is ~10 pixels off. So the effect is that the top line of the scroll view is almost pinned to the top, but not quite, and it's distracting.

Is there a better way to do this? Here's the relevant code:

- (void)windowDidResize:(NSNotification *)notification;
{
    if ([notification object] == mainWindow) {
        CGFloat currentWindowHeight = [mainWindow frame].size.height;

        // previousWindowHeight is an ivar
        NSNumber *heightDeltaNum = [NSNumber numberWithFloat:(currentWindowHeight - previousWindowHeight)];
        previousWindowHeight = currentWindowHeight;
        [[NSNotificationCenter defaultCenter] postNotificationName:@"AFSnapScrollView" object:heightDeltaNum];
    }
}

- (void)snapScrollViewNotification:(NSNotification *)theNotification;
{
    [self snapScrollView];

    NSNumber *heightDeltaNum = [theNotification object];

    CGFloat newY = [[tagScrollView documentView] visibleRect].origin.y - [heightDeltaNum floatValue];
    NSPoint pointToScroll = NSMakePoint(0,newY);
    [[tagScrollView documentView] scrollPoint:pointToScroll];
}

- (void)snapScrollView;
{

    [...]

    // adjust the view frame
    [[tagScrollView documentView] setFrame:NSMakeRect(0, 0, existingDocumentFrame.size.width, newDocumentViewHeight)];

    [...]

}
like image 905
Simone Manganelli Avatar asked Dec 23 '22 00:12

Simone Manganelli


2 Answers

Your document view needs to override the -(BOOL)isFlipped method and return YES.

like image 187
Chris Suter Avatar answered Mar 03 '23 14:03

Chris Suter


turning clipview not need to modify documentView, after flip coordinates.

@interface FlippedClipView : NSClipView 
@end

@implementation FlippedClipView
- (BOOL)isFlipped
{
    return YES;
}
@end
like image 24
Roman Solodyashkin Avatar answered Mar 03 '23 14:03

Roman Solodyashkin