1//SBCenteringClipView.m 2//Created by Brock Brandenberg 3//Who is much cooler than we are. Maybe. 4 5#import "SBCenteringClipView.h" 6 7@implementation SBCenteringClipView 8 9// ---------------------------------------- 10 11-(void)centerDocument 12{ 13 NSRect docRect = [[self documentView] frame]; 14 NSRect clipRect = [self bounds]; 15 16 // We can leave these values as integers (don't need the "2.0") 17 if( docRect.size.width < clipRect.size.width ) 18 clipRect.origin.x = roundf( ( docRect.size.width - clipRect.size.width ) / 2.0 ); 19 20 if( docRect.size.height < clipRect.size.height ) 21 clipRect.origin.y = roundf( ( docRect.size.height - clipRect.size.height ) / 2.0 ); 22 23 // Probably the most efficient way to move the bounds origin. 24 [self scrollToPoint:clipRect.origin]; 25 26 // We could use this instead since it allows a scroll view to coordinate scrolling between multiple clip views. 27 // [[self superview] scrollClipView:self toPoint:clipRect.origin]; 28} 29 30// ---------------------------------------- 31// We need to override this so that the superclass doesn't override our new origin point. 32 33-(NSPoint)constrainScrollPoint:(NSPoint)proposedNewOrigin 34{ 35 NSRect docRect = [[self documentView] frame]; 36 NSRect clipRect = [self bounds]; 37 NSPoint newScrollPoint = proposedNewOrigin; 38 float maxX = docRect.size.width - clipRect.size.width; 39 float maxY = docRect.size.height - clipRect.size.height; 40 41 // If the clip view is wider than the doc, we can't scroll horizontally 42 if( docRect.size.width < clipRect.size.width ) 43 newScrollPoint.x = roundf( maxX / 2.0 ); 44 else 45 newScrollPoint.x = roundf( MAX(0,MIN(newScrollPoint.x,maxX)) ); 46 47 // If the clip view is taller than the doc, we can't scroll vertically 48 if( docRect.size.height < clipRect.size.height ) 49 newScrollPoint.y = roundf( maxY / 2.0 ); 50 else 51 newScrollPoint.y = roundf( MAX(0,MIN(newScrollPoint.y,maxY)) ); 52 53 return newScrollPoint; 54} 55 56// ---------------------------------------- 57// These two methods get called whenever the subview changes 58 59-(void)viewBoundsChanged:(NSNotification *)notification 60{ 61 [super viewBoundsChanged:notification]; 62 [self centerDocument]; 63} 64 65-(void)viewFrameChanged:(NSNotification *)notification 66{ 67 [super viewFrameChanged:notification]; 68 [self centerDocument]; 69} 70 71// ---------------------------------------- 72// These superclass methods change the bounds rect directly without sending any notifications, 73// so we're not sure what other work they silently do for us. As a result, we let them do their 74// work and then swoop in behind to change the bounds origin ourselves. This appears to work 75// just fine without us having to reinvent the methods from scratch. 76 77- (void)setFrame:(NSRect)frameRect 78{ 79 [super setFrame:frameRect]; 80 [self centerDocument]; 81} 82 83- (void)setFrameOrigin:(NSPoint)newOrigin 84{ 85 [super setFrameOrigin:newOrigin]; 86 [self centerDocument]; 87} 88 89- (void)setFrameSize:(NSSize)newSize 90{ 91 [super setFrameSize:newSize]; 92 [self centerDocument]; 93} 94 95- (void)setFrameRotation:(float)angle 96{ 97 [super setFrameRotation:angle]; 98 [self centerDocument]; 99} 100 101@end 102