NSScrollView滚动垂直滚动水平

时间:2013-03-12 16:52:48

标签: objective-c macos nsscrollview

如果我垂直滚动NSScrollView,它会自动水平滚动。为什么?我使用AGCenteringClipView作为contentView。


正如你所问,这是代码 的 AGCenteringClipView.m

#import "AGCenteringClipView.h"


@implementation AGCenteringClipView
- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        mLookingAt = NSMakePoint(0, 0);
        [self setAutoresizesSubviews:NO];
    }
    return self;

}
- (void)centerDocument
{
    NSRect docRect = [[self documentView] frame];
    NSRect clipRect = [self bounds];

    // The origin point should have integral values or drawing anomalies will occur.
    // We'll leave it to the constrainScrollPoint: method to do it for us.
    if (docRect.size.width < clipRect.size.width) {
        clipRect.origin.x = (docRect.size.width - clipRect.size.width) / 2.0;
    } else {
        clipRect.origin.x = mLookingAt.x * docRect.size.width - (clipRect.size.width / 2.0);
    }


    if (docRect.size.height < clipRect.size.height) {
        clipRect.origin.y = (docRect.size.height - clipRect.size.height) / 2.0;
    } else {
        clipRect.origin.y = mLookingAt.y * docRect.size.height - (clipRect.size.height / 2.0);
    }

    // Probably the best way to move the bounds origin.
    // Make sure that the scrollToPoint contains integer values
    // or the NSView will smear the drawing under certain circumstances.
    [self scrollToPoint:[self constrainScrollPoint:clipRect.origin]];
//  [[self superview] reflectScrolledClipView:self];
}


// ----------------------------------------
// We need to override this so that the superclass doesn't override our new origin point.
- (NSPoint)constrainScrollPoint:(NSPoint)proposedNewOrigin
{
    NSRect docRect = [[self documentView] frame];
    NSRect clipRect = [self bounds];
    CGFloat maxX = docRect.size.width - clipRect.size.width;
    CGFloat maxY = docRect.size.height - clipRect.size.height;

    clipRect.origin = proposedNewOrigin; // shift origin to proposed location

    // If the clip view is wider than the doc, we can't scroll horizontally
    if (docRect.size.width < clipRect.size.width) {
        clipRect.origin.x = round( maxX / 2.0 );
    } else {
        clipRect.origin.x = round( MAX(0,MIN(clipRect.origin.x,maxX)) );
    }

    // If the clip view is taller than the doc, we can't scroll vertically
    if (docRect.size.height < clipRect.size.height) {
        clipRect.origin.y = round( maxY / 2.0 );
    } else {
        clipRect.origin.y = round( MAX(0,MIN(clipRect.origin.y,maxY)) );
    }

    // Save center of view as proportions so we can later tell where the user was focused.
    mLookingAt.x = NSMidX(clipRect) / docRect.size.width;
    mLookingAt.y = NSMidY(clipRect) / docRect.size.height;

    // The docRect isn't necessarily at (0, 0) so when it isn't, this correctly creates the correct scroll point
    return NSMakePoint(docRect.origin.x + clipRect.origin.x, docRect.origin.y + clipRect.origin.y);
}



// ----------------------------------------
// These two methods get called whenever the NSClipView's subview changes.
// We save the old center of interest, call the superclass to let it do its work,
// then move the scroll point to try and put the old center of interest
// back in the center of the view if possible.

- (void)viewBoundsChanged:(NSNotification *)notification
{
    NSPoint savedPoint = mLookingAt;
    [super viewBoundsChanged:notification];
    mLookingAt = savedPoint;
    [self centerDocument];
}

- (void)viewFrameChanged:(NSNotification *)notification
{
    NSPoint savedPoint = mLookingAt;
    [super viewFrameChanged:notification];
    mLookingAt = savedPoint;
    [self centerDocument];
}

// ----------------------------------------
// We have some redundancy in the fact that setFrame: appears to call/send setFrameOrigin:
// and setFrameSize: to do its work, but we need to override these individual methods in case
// either one gets called independently. Because none of them explicitly cause a screen update,
// it's ok to do a little extra work behind the scenes because it wastes very little time.
// It's probably the result of a single UI action anyway so it's not like it's slowing
// down a huge iteration by being called thousands of times.

- (void)setFrameOrigin:(NSPoint)newOrigin
{
    if (!NSEqualPoints(self.frame.origin, newOrigin)) {
        [super setFrameOrigin:newOrigin];
        [self centerDocument];
    }
}

- (void)setFrameSize:(NSSize)newSize
{
    if (!NSEqualSizes(self.frame.size, newSize)) {
        [super setFrameSize:newSize];
        [self centerDocument];
    }
}

- (void)setFrameRotation:(CGFloat)angle
{
    [super setFrameRotation:angle];
    [self centerDocument];
}

NSScrollView没有代码。它甚至没有子类。

0 个答案:

没有答案