diff --git a/src/MacVim/Actions.plist b/src/MacVim/Actions.plist index 458fd66e29..920f48d98a 100644 --- a/src/MacVim/Actions.plist +++ b/src/MacVim/Actions.plist @@ -6,6 +6,8 @@ arrangeInFront: + clearRecentDocuments: + fileOpen: findNext: @@ -38,6 +40,8 @@ performZoom: + recentFilesDummy: + selectNextWindow: selectPreviousWindow: diff --git a/src/MacVim/MMAppController.h b/src/MacVim/MMAppController.h index 9b5db2f063..c464cf116d 100644 --- a/src/MacVim/MMAppController.h +++ b/src/MacVim/MMAppController.h @@ -20,6 +20,8 @@ NSString *openSelectionString; ATSFontContainerRef fontContainerRef; NSMutableDictionary *pidArguments; + + NSMenuItem *recentFilesMenuItem; } - (void)removeVimController:(id)controller; diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index 38a33fda51..d3755fc444 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -171,20 +171,45 @@ static int executeInLoginShell(NSString *path, NSArray *args); [pidArguments release]; pidArguments = nil; [vimControllers release]; vimControllers = nil; [openSelectionString release]; openSelectionString = nil; + [recentFilesMenuItem release]; recentFilesMenuItem = nil; [super dealloc]; } -#if MM_HANDLE_XCODE_MOD_EVENT - (void)applicationWillFinishLaunching:(NSNotification *)notification { + // Create the "Open Recent" menu. See + // http://lapcatsoftware.com/blog/2007/07/10/working-without-a-nib-part-5-open-recent-menu/ + // and http://www.cocoabuilder.com/archive/message/cocoa/2007/8/15/187793 + // for more information. + // + // The menu needs to be created and be added to a toplevel menu in + // applicationWillFinishLaunching at the latest, otherwise it doesn't work. + + recentFilesMenuItem = [[NSMenuItem alloc] initWithTitle:@"Open Recent" + action:nil keyEquivalent:@""]; + + NSMenu *recentFilesMenu = [[NSMenu alloc] initWithTitle:@"Open Recent"]; + [recentFilesMenu performSelector:@selector(_setMenuName:) + withObject:@"NSRecentDocumentsMenu"]; + + [recentFilesMenu addItemWithTitle:@"Clear Menu" + action:@selector(clearRecentDocuments:) + keyEquivalent:@""]; + [recentFilesMenuItem setSubmenu:recentFilesMenu]; + [recentFilesMenu release]; // the menu is retained by recentFilesMenuItem + [recentFilesMenuItem setTag:-1]; // must not be 0 + + [[[[NSApp mainMenu] itemWithTitle:@"File"] submenu] addItem:recentFilesMenuItem]; + +#if MM_HANDLE_XCODE_MOD_EVENT [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleXcodeModEvent:replyEvent:) forEventClass:'KAHL' andEventID:'MOD ']; -} #endif +} - (void)applicationDidFinishLaunching:(NSNotification *)notification { @@ -261,6 +286,18 @@ static int executeInLoginShell(NSString *path, NSArray *args); [arguments setObject:filenames forKey:@"filenames"]; [arguments setObject:[NSNumber numberWithBool:YES] forKey:@"openFiles"]; + // Add file names to "Recent Files" menu. + int i, count = [filenames count]; + for (i = 0; i < count; ++i) { + // Don't add files that are being edited remotely (using ODB). + if ([arguments objectForKey:@"remoteID"]) continue; + + NSURL *url = [NSURL fileURLWithPath:[filenames objectAtIndex:i]]; + if (!url) continue; + [[NSDocumentController sharedDocumentController] + noteNewRecentDocumentURL:url]; + } + if ((openInTabs && (vc = [self topmostVimController])) || (vc = [self findUntitledWindow])) { // Open files in an already open window. @@ -599,7 +636,8 @@ static int executeInLoginShell(NSString *path, NSArray *args); setProtocolForProxy:@protocol(MMBackendProtocol)]; vc = [[[MMVimController alloc] - initWithBackend:backend pid:pid] autorelease]; + initWithBackend:backend pid:pid recentFiles:recentFilesMenuItem] + autorelease]; if (![vimControllers count]) { // The first window autosaves its position. (The autosaving diff --git a/src/MacVim/MMVimController.h b/src/MacVim/MMVimController.h index a4889de3fc..59bd4dd31a 100644 --- a/src/MacVim/MMVimController.h +++ b/src/MacVim/MMVimController.h @@ -40,9 +40,12 @@ NSData *resendData; #endif NSMenu *lastMenuSearched; + NSMenuItem *recentFilesMenuItem; + NSMenuItem *recentFilesDummy; } -- (id)initWithBackend:(id)backend pid:(int)processIdentifier; +- (id)initWithBackend:(id)backend pid:(int)processIdentifier + recentFiles:(NSMenuItem*)menu; - (id)backendProxy; - (int)pid; - (void)setServerName:(NSString *)name; diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index 1c1b77dc55..7cb5ac8980 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -81,6 +81,7 @@ static NSTimeInterval MMResendInterval = 0.5; #if MM_RESEND_LAST_FAILURE - (void)resendTimerFired:(NSTimer *)timer; #endif +- (void)replaceMenuItem:(NSMenuItem*)old with:(NSMenuItem*)new; @end @@ -89,8 +90,12 @@ static NSTimeInterval MMResendInterval = 0.5; @implementation MMVimController - (id)initWithBackend:(id)backend pid:(int)processIdentifier + recentFiles:(NSMenuItem*)menu; { if ((self = [super init])) { + + recentFilesMenuItem = [menu retain]; + windowController = [[MMWindowController alloc] initWithVimController:self]; backendProxy = [backend retain]; @@ -135,6 +140,9 @@ static NSTimeInterval MMResendInterval = 0.5; [mainMenuItems release]; mainMenuItems = nil; [windowController release]; windowController = nil; + [recentFilesMenuItem release]; recentFilesMenuItem = nil; + [recentFilesDummy release]; recentFilesDummy = nil; + [super dealloc]; } @@ -574,6 +582,14 @@ static NSTimeInterval MMResendInterval = 0.5; [NSApp setWindowsMenu:windowMenu]; } + // Replace real Recent Files menu in the old menu with the dummy, then + // remove dummy from new menu and put Recent Files menu there + NSMenuItem *oldItem = (NSMenuItem*)[recentFilesMenuItem representedObject]; + if (oldItem) + [self replaceMenuItem:recentFilesMenuItem with:oldItem]; + [recentFilesMenuItem setRepresentedObject:recentFilesDummy]; + [self replaceMenuItem:recentFilesDummy with:recentFilesMenuItem]; + shouldUpdateMainMenu = NO; } @@ -1073,17 +1089,28 @@ static NSTimeInterval MMResendInterval = 0.5; } else { item = [[[NSMenuItem alloc] init] autorelease]; [item setTitle:title]; - // TODO: Check that 'action' is a valid action (nothing will happen - // if it isn't, but it would be nice with a warning). - if (action) [item setAction:NSSelectorFromString(action)]; - else [item setAction:@selector(vimMenuItemAction:)]; - if (tip) [item setToolTip:tip]; - if (key != 0) { - NSString *keyString = - [NSString stringWithFormat:@"%C", key]; - [item setKeyEquivalent:keyString]; - [item setKeyEquivalentModifierMask:mask]; + if ([action isEqualToString:@"recentFilesDummy:"]) { + // Remove the recent files menu item from its current menu + // and put it in the current file menu. See -[MMAppController + // applicationWillFinishLaunching for more information. + //[[recentFilesMenuItem menu] removeItem:recentFilesMenuItem]; + //item = recentFilesMenuItem; + recentFilesDummy = [item retain]; + + } else { + // TODO: Check that 'action' is a valid action (nothing will + // happen if it isn't, but it would be nice with a warning). + if (action) [item setAction:NSSelectorFromString(action)]; + else [item setAction:@selector(vimMenuItemAction:)]; + if (tip) [item setToolTip:tip]; + + if (key != 0) { + NSString *keyString = + [NSString stringWithFormat:@"%C", key]; + [item setKeyEquivalent:keyString]; + [item setKeyEquivalentModifierMask:mask]; + } } } @@ -1220,6 +1247,14 @@ static NSTimeInterval MMResendInterval = 0.5; } #endif +- (void)replaceMenuItem:(NSMenuItem*)old with:(NSMenuItem*)new +{ + NSMenu *menu = [old menu]; + int index = [menu indexOfItem:old]; + [menu removeItemAtIndex:index]; + [menu insertItem:new atIndex:index]; +} + @end // MMVimController (Private) diff --git a/src/MacVim/gvimrc b/src/MacVim/gvimrc index 827ca9a2cc..ca9910c75a 100644 --- a/src/MacVim/gvimrc +++ b/src/MacVim/gvimrc @@ -45,6 +45,7 @@ aunmenu File.Save-Exit an 10.290 File.New\ Window :maca newWindow: an 10.295 File.New\ Tab :tabnew an 10.310 File.&Open\.\.\. :maca fileOpen: +an 10.314 File.Open\ Recent :maca recentFilesDummy: an 10.328 File.-SEP0- an 10.330 File.Close\ Window:qa :confirm qa an 10.331 File.Close :maca performClose: