====== zoom centered on point ====== - (void)zoom:(id)sender mode:(int)mode { // find the base value of the currently viewed centerpoint (no scaleFactor) NSClipView *cv = (NSClipView *)[self superview]; NSRect docVisRect = [cv documentVisibleRect]; NSPoint viewCenterPoint; viewCenterPoint.x = ( docVisRect.origin.x + (docVisRect.size.width / 2.) ) * 1/scaleFactor; viewCenterPoint.y = ( docVisRect.origin.y + (docVisRect.size.height / 2.) ) * 1/scaleFactor; if(mode == ZOOM_IN){ // the NSSlider won't allow values outside of our min/max, so this is safe [sfSlider setFloatValue:scaleFactor + KEY_ZOOM_INCREMENT]; }else if(mode == ZOOM_OUT){ // the NSSlider won't allow values outside of our min/max, so this is safe [sfSlider setFloatValue:scaleFactor - KEY_ZOOM_INCREMENT]; } [self changeScale:self]; // this also updates the display (frame, etc...) // transform the point using the new scaleFactor NSPoint scaledCenterPoint; scaledCenterPoint.x = viewCenterPoint.x * scaleFactor; scaledCenterPoint.y = viewCenterPoint.y * scaleFactor; // calculate the new origin - we must scroll to a new origin, not to a new center point NSPoint newOrigin; docVisRect = [cv documentVisibleRect]; newOrigin.x = scaledCenterPoint.x - (docVisRect.size.width / 2.); newOrigin.y = scaledCenterPoint.y - (docVisRect.size.height / 2.); // force the NSScrollView to scroll to the new point [cv scrollToPoint:[cv constrainScrollPoint:newOrigin]]; [self setNeedsDisplay:YES]; // make sure the scroll bars are updated [[[self superview] superview] reflectScrolledClipView:cv]; }