diff --git a/Applications/Review/AppController.h b/Applications/Review/AppController.h index f19862d87..59b256b6a 100644 --- a/Applications/Review/AppController.h +++ b/Applications/Review/AppController.h @@ -45,4 +45,7 @@ - (void)setDefaultSize:(id)sender; //Info Panel - (void)showInfoPanel:(id)sender; + +- (void)zoomIn:(id)sender; +- (void)zoomOut:(id)sender; @end diff --git a/Applications/Review/AppController.m b/Applications/Review/AppController.m index dcf824e1e..67ae0cfb3 100644 --- a/Applications/Review/AppController.m +++ b/Applications/Review/AppController.m @@ -37,6 +37,25 @@ - (void)dealloc - (void)applicationDidFinishLaunching:(NSNotification *)notif { + NSMenu *mainMenu = [NSApp mainMenu]; + NSMenuItem *displayItem = (NSMenuItem *)[mainMenu itemWithTitle:@"Display"]; + if (displayItem) { + NSMenu *displayMenu = [displayItem submenu]; + NSMenuItem *zoomInItem = (NSMenuItem *)[displayMenu itemWithTitle:@"Zoom In"]; + NSMenuItem *zoomOutItem = (NSMenuItem *)[displayMenu itemWithTitle:@"Zoom Out"]; + if (zoomInItem) { + [zoomInItem setTarget:self]; + [zoomInItem setAction:@selector(zoomIn:)]; + [zoomInItem setKeyEquivalent:@"="]; + [zoomInItem setKeyEquivalentModifierMask:NSCommandKeyMask]; + } + if (zoomOutItem) { + [zoomOutItem setTarget:self]; + [zoomOutItem setAction:@selector(zoomOut:)]; + [zoomOutItem setKeyEquivalent:@"-"]; + [zoomOutItem setKeyEquivalentModifierMask:NSCommandKeyMask]; + } + } } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender @@ -149,6 +168,40 @@ - (void)saveImageAs:(id)sender } } +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + if ([menuItem action] == @selector(zoomIn:) || [menuItem action] == @selector(zoomOut:)) { + NSWindow *keyWindow = [NSApp keyWindow]; + for (ImageWindow *win in imageWindows) { + if (win.window == keyWindow) return YES; + } + return NO; + } + return YES; +} + +- (void)zoomIn:(id)sender +{ + NSWindow *keyWindow = [NSApp keyWindow]; + for (ImageWindow *win in imageWindows) { + if (win.window == keyWindow) { + [win zoomIn]; + return; + } + } +} + +- (void)zoomOut:(id)sender +{ + NSWindow *keyWindow = [NSApp keyWindow]; + for (ImageWindow *win in imageWindows) { + if (win.window == keyWindow) { + [win zoomOut]; + return; + } + } +} + - (void)imageWindowWillClose:(id)sender { if (sender) { diff --git a/Applications/Review/English.lproj/Review.gorm/data.classes b/Applications/Review/English.lproj/Review.gorm/data.classes index c1cbe5de6..84ef719e7 100644 --- a/Applications/Review/English.lproj/Review.gorm/data.classes +++ b/Applications/Review/English.lproj/Review.gorm/data.classes @@ -6,7 +6,9 @@ "openImage:", "showInfoPanel:", "saveImageAs:", - "showInspector:" + "showInspector:", + "zoomIn:", + "zoomOut:" ); Outlets = ( infoPanel diff --git a/Applications/Review/ImageWindow.h b/Applications/Review/ImageWindow.h index dba961d32..c15a5cd17 100644 --- a/Applications/Review/ImageWindow.h +++ b/Applications/Review/ImageWindow.h @@ -68,6 +68,8 @@ - (NSString *)imageProgressive; - (void)scaleImageFromPopup:(id)sender; +- (void)zoomIn; +- (void)zoomOut; @end diff --git a/Applications/Review/ImageWindow.m b/Applications/Review/ImageWindow.m index 93770ed58..7869c8737 100644 --- a/Applications/Review/ImageWindow.m +++ b/Applications/Review/ImageWindow.m @@ -284,11 +284,12 @@ - (id)initWithContentsOfFile:(NSString *)path NSLog(@"Representaion: %li x %li", rep.pixelsWide, rep.pixelsHigh); } frame = [NSWindow frameRectForContentRect:frame styleMask:wMask]; - if (imageSize.width > ([[NSScreen mainScreen] frame].size.width - 64)) { - frame.size.width = [[NSScreen mainScreen] frame].size.width - 164; - } - if (imageSize.height > ([[NSScreen mainScreen] frame].size.height - 64)) { - frame.size.height = [[NSScreen mainScreen] frame].size.height - 64; + { + NSRect sf = [[NSScreen mainScreen] visibleFrame]; + CGFloat maxW = floor(sf.size.width * 0.70); + CGFloat maxH = floor(sf.size.height * 0.70); + if (frame.size.width > maxW) frame.size.width = maxW; + if (frame.size.height > maxH) frame.size.height = maxH; } if (frame.size.width < 100) frame.size.width = 100; @@ -302,7 +303,13 @@ - (id)initWithContentsOfFile:(NSString *)path [_window setReleasedWhenClosed:YES]; [_window setDelegate:self]; [_window setFrame:frame display:YES]; - [_window setMaxSize:frame.size]; + { + NSRect sf = [[NSScreen mainScreen] visibleFrame]; + NSSize maxContent = NSMakeSize(floor(sf.size.width * 0.70), floor(sf.size.height * 0.70)); + NSSize maxWinSize = [NSWindow frameRectForContentRect:NSMakeRect(0, 0, maxContent.width, maxContent.height) + styleMask:wMask].size; + [_window setMaxSize:maxWinSize]; + } [_window setMinSize:NSMakeSize(200, 200)]; [_window setContentView:box]; RELEASE(box); @@ -317,6 +324,35 @@ - (id)initWithContentsOfFile:(NSString *)path return self; } +- (void)_resizeWindowForImageSize:(NSSize)scaledSize +{ + NSScreen *screen = [_window screen]; + if (!screen) screen = [NSScreen mainScreen]; + NSRect sf = [screen visibleFrame]; + + CGFloat maxW = floor(sf.size.width * 0.70); + CGFloat maxH = floor(sf.size.height * 0.70); + + NSSize contentSize; + contentSize.width = MAX(200.0, MIN(scaledSize.width, maxW)); + contentSize.height = MAX(200.0, MIN(scaledSize.height, maxH)); + + NSRect newFrame = [NSWindow frameRectForContentRect:NSMakeRect(0, 0, contentSize.width, contentSize.height) + styleMask:[_window styleMask]]; + + NSRect cur = [_window frame]; + newFrame.origin.x = NSMidX(cur) - newFrame.size.width / 2.0; + newFrame.origin.y = NSMidY(cur) - newFrame.size.height / 2.0; + + // Clamp so window stays on screen + if (newFrame.origin.x < sf.origin.x) newFrame.origin.x = sf.origin.x; + if (newFrame.origin.y < sf.origin.y) newFrame.origin.y = sf.origin.y; + if (NSMaxX(newFrame) > NSMaxX(sf)) newFrame.origin.x = NSMaxX(sf) - newFrame.size.width; + if (NSMaxY(newFrame) > NSMaxY(sf)) newFrame.origin.y = NSMaxY(sf) - newFrame.size.height; + + [_window setFrame:newFrame display:YES]; +} + - (void)scaleImageFromPopup:(id)sender { NSString *title = [scalePopup titleOfSelectedItem]; @@ -328,13 +364,41 @@ - (void)scaleImageFromPopup:(id)sender NSSize scaledSize = NSMakeSize(round(baseSize.width * factor), round(baseSize.height * factor)); - /* Resize the image to the scaled size — NSImageView will stretch it */ [_image setSize:scaledSize]; - [imageView setFrameSize:scaledSize]; + + /* Resize window first so the scroll view has its final content area size */ + [self _resizeWindowForImageSize:scaledSize]; + + /* Size imageView to at least fill the visible area so NSImageAlignCenter + keeps the image centered when it is smaller than the scroll view */ + NSScrollView *sv = [imageView enclosingScrollView]; + NSSize contentSize = sv ? [sv contentSize] : scaledSize; + NSSize viewSize = NSMakeSize(MAX(scaledSize.width, contentSize.width), + MAX(scaledSize.height, contentSize.height)); + + [imageView setFrameSize:viewSize]; [imageView setImage:nil]; /* force redraw */ [imageView setImage:_image]; } +- (void)zoomIn +{ + NSInteger idx = [scalePopup indexOfSelectedItem]; + if (idx < [scalePopup numberOfItems] - 1) { + [scalePopup selectItemAtIndex:idx + 1]; + [self scaleImageFromPopup:scalePopup]; + } +} + +- (void)zoomOut +{ + NSInteger idx = [scalePopup indexOfSelectedItem]; + if (idx > 0) { + [scalePopup selectItemAtIndex:idx - 1]; + [self scaleImageFromPopup:scalePopup]; + } +} + - (void)dealloc { RELEASE(_window);