From ff0e9531ee1c5b1c28e8c967025581e0747e1785 Mon Sep 17 00:00:00 2001 From: Bjorn Winckler Date: Sun, 5 Apr 2009 18:57:56 +0200 Subject: [PATCH] Add support for dialogs --- src/MacVim/MMAppController.m | 9 ++ src/MacVim/MMBackend.m | 19 ++- src/MacVim/MMVimController.m | 281 ++++++++++++++++++++++--------------------- src/MacVim/MacVim.h | 2 + src/MacVim/MacVim.m | 2 + 5 files changed, 166 insertions(+), 147 deletions(-) diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index 067e902c..e45504d6 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -1183,6 +1183,15 @@ fsEventCallback(ConstFSEventStreamRef streamRef, NSLog(@"[%s] Appending queue id=%d", _cmd, identifier); q = [q arrayByAddingObjectsFromArray:queue]; [inputQueues setObject:q forKey:key]; + +#if 0 // More debug logging info + unsigned i, count = [q count]; + for (i = 0; i < count; i += 2) { + NSData *value = [q objectAtIndex:i]; + int msgid = *((int*)[value bytes]); + NSLog(@" %s", MessageStrings[msgid]); + } +#endif } else { [inputQueues setObject:queue forKey:key]; } diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 8bafaf5a..8344b250 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -691,10 +691,10 @@ extern GuiFont gui_mch_retain_font(GuiFont font); { char_u *s = NULL; -#if 0 - @try { - [frontendProxy showSavePanelWithAttributes:attr]; + [self queueMessage:BrowseForFileMsgID properties:attr]; + [self flushQueue:YES]; + @try { [self waitForDialogReturn]; if (dialogReturn && [dialogReturn isKindOfClass:[NSString class]]) @@ -703,9 +703,9 @@ extern GuiFont gui_mch_retain_font(GuiFont font); [dialogReturn release]; dialogReturn = nil; } @catch (NSException *e) { - NSLog(@"Exception caught when showing save panel: \"%@\"", e); + NSLog(@"[%s] Exception caught: \"%@\"", _cmd, e); } -#endif + return (char *)s; } @@ -731,10 +731,10 @@ extern GuiFont gui_mch_retain_font(GuiFont font); { int retval = 0; -#if 0 - @try { - [frontendProxy presentDialogWithAttributes:attr]; + [self queueMessage:ShowDialogMsgID properties:attr]; + [self flushQueue:YES]; + @try { [self waitForDialogReturn]; if (dialogReturn && [dialogReturn isKindOfClass:[NSArray class]] @@ -756,9 +756,8 @@ extern GuiFont gui_mch_retain_font(GuiFont font); [dialogReturn release]; dialogReturn = nil; } @catch (NSException *e) { - NSLog(@"Exception caught while showing alert dialog: \"%@\"", e); + NSLog(@"[%s] Exception caught: \"%@\"", _cmd, e); } -#endif return retval; } diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index 62fe0e1f..78ad67a4 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -97,6 +97,8 @@ static unsigned identifierCounter = 1; - (void)popupMenuWithAttributes:(NSDictionary *)attrs; - (void)connectionDidDie:(NSNotification *)notification; - (void)scheduleClose; +- (void)handleBrowseForFile:(NSDictionary *)attr; +- (void)handleShowDialog:(NSDictionary *)attr; @end @@ -439,143 +441,6 @@ static unsigned identifierCounter = 1; [windowController cleanup]; } -#if 0 -- (oneway void)showSavePanelWithAttributes:(in bycopy NSDictionary *)attr -{ - if (!isInitialized) return; - - BOOL inDefaultMode = [[[NSRunLoop currentRunLoop] currentMode] - isEqual:NSDefaultRunLoopMode]; - if (!inDefaultMode) { - // Delay call until run loop is in default mode. - [self performSelectorOnMainThread: - @selector(showSavePanelWithAttributes:) - withObject:attr - waitUntilDone:NO - modes:[NSArray arrayWithObject: - NSDefaultRunLoopMode]]; - return; - } - - NSString *dir = [attr objectForKey:@"dir"]; - BOOL saving = [[attr objectForKey:@"saving"] boolValue]; - - if (!dir) { - // 'dir == nil' means: set dir to the pwd of the Vim process, or let - // open dialog decide (depending on the below user default). - BOOL trackPwd = [[NSUserDefaults standardUserDefaults] - boolForKey:MMDialogsTrackPwdKey]; - if (trackPwd) - dir = [vimState objectForKey:@"pwd"]; - } - - if (saving) { - [[NSSavePanel savePanel] beginSheetForDirectory:dir file:nil - modalForWindow:[windowController window] - modalDelegate:self - didEndSelector:@selector(savePanelDidEnd:code:context:) - contextInfo:NULL]; - } else { - NSOpenPanel *panel = [NSOpenPanel openPanel]; - [panel setAllowsMultipleSelection:NO]; - [panel setAccessoryView:openPanelAccessoryView()]; - - [panel beginSheetForDirectory:dir file:nil types:nil - modalForWindow:[windowController window] - modalDelegate:self - didEndSelector:@selector(savePanelDidEnd:code:context:) - contextInfo:NULL]; - } -} - -- (oneway void)presentDialogWithAttributes:(in bycopy NSDictionary *)attr -{ - if (!isInitialized) return; - - BOOL inDefaultMode = [[[NSRunLoop currentRunLoop] currentMode] - isEqual:NSDefaultRunLoopMode]; - if (!inDefaultMode) { - // Delay call until run loop is in default mode. - [self performSelectorOnMainThread: - @selector(presentDialogWithAttributes:) - withObject:attr - waitUntilDone:NO - modes:[NSArray arrayWithObject: - NSDefaultRunLoopMode]]; - return; - } - - NSArray *buttonTitles = [attr objectForKey:@"buttonTitles"]; - if (!(buttonTitles && [buttonTitles count])) return; - - int style = [[attr objectForKey:@"alertStyle"] intValue]; - NSString *message = [attr objectForKey:@"messageText"]; - NSString *text = [attr objectForKey:@"informativeText"]; - NSString *textFieldString = [attr objectForKey:@"textFieldString"]; - MMAlert *alert = [[MMAlert alloc] init]; - - // NOTE! This has to be done before setting the informative text. - if (textFieldString) - [alert setTextFieldString:textFieldString]; - - [alert setAlertStyle:style]; - - if (message) { - [alert setMessageText:message]; - } else { - // If no message text is specified 'Alert' is used, which we don't - // want, so set an empty string as message text. - [alert setMessageText:@""]; - } - - if (text) { - [alert setInformativeText:text]; - } else if (textFieldString) { - // Make sure there is always room for the input text field. - [alert setInformativeText:@""]; - } - - unsigned i, count = [buttonTitles count]; - for (i = 0; i < count; ++i) { - NSString *title = [buttonTitles objectAtIndex:i]; - // NOTE: The title of the button may contain the character '&' to - // indicate that the following letter should be the key equivalent - // associated with the button. Extract this letter and lowercase it. - NSString *keyEquivalent = nil; - NSRange hotkeyRange = [title rangeOfString:@"&"]; - if (NSNotFound != hotkeyRange.location) { - if ([title length] > NSMaxRange(hotkeyRange)) { - NSRange keyEquivRange = NSMakeRange(hotkeyRange.location+1, 1); - keyEquivalent = [[title substringWithRange:keyEquivRange] - lowercaseString]; - } - - NSMutableString *string = [NSMutableString stringWithString:title]; - [string deleteCharactersInRange:hotkeyRange]; - title = string; - } - - [alert addButtonWithTitle:title]; - - // Set key equivalent for the button, but only if NSAlert hasn't - // already done so. (Check the documentation for - // - [NSAlert addButtonWithTitle:] to see what key equivalents are - // automatically assigned.) - NSButton *btn = [[alert buttons] lastObject]; - if ([[btn keyEquivalent] length] == 0 && keyEquivalent) { - [btn setKeyEquivalent:keyEquivalent]; - } - } - - [alert beginSheetModalForWindow:[windowController window] - modalDelegate:self - didEndSelector:@selector(alertDidEnd:code:context:) - contextInfo:NULL]; - - [alert release]; -} -#endif - - (void)processInputQueue:(NSArray *)queue { if (!isInitialized) return; @@ -995,6 +860,14 @@ static unsigned identifierCounter = 1; KeyScript(smKeySysScript); } else if (DeactivateKeyScriptID == msgid) { KeyScript(smKeyRoman); + } else if (BrowseForFileMsgID == msgid) { + NSDictionary *dict = [NSDictionary dictionaryWithData:data]; + if (dict) + [self handleBrowseForFile:dict]; + } else if (ShowDialogMsgID == msgid) { + NSDictionary *dict = [NSDictionary dictionaryWithData:data]; + if (dict) + [self handleShowDialog:dict]; // IMPORTANT: When adding a new message, make sure to update // isUnsafeMessage() if necessary! } else { @@ -1449,6 +1322,140 @@ static unsigned identifierCounter = 1; NSDefaultRunLoopMode]]; } +- (void)handleBrowseForFile:(NSDictionary *)attr +{ + if (!isInitialized) return; + + BOOL inDefaultMode = [[[NSRunLoop currentRunLoop] currentMode] + isEqual:NSDefaultRunLoopMode]; + if (!inDefaultMode) { + // Delay call until run loop is in default mode. + [self performSelectorOnMainThread:@selector(handleBrowseForFile:) + withObject:attr + waitUntilDone:NO + modes:[NSArray arrayWithObject: + NSDefaultRunLoopMode]]; + return; + } + + NSString *dir = [attr objectForKey:@"dir"]; + BOOL saving = [[attr objectForKey:@"saving"] boolValue]; + + if (!dir) { + // 'dir == nil' means: set dir to the pwd of the Vim process, or let + // open dialog decide (depending on the below user default). + BOOL trackPwd = [[NSUserDefaults standardUserDefaults] + boolForKey:MMDialogsTrackPwdKey]; + if (trackPwd) + dir = [vimState objectForKey:@"pwd"]; + } + + if (saving) { + [[NSSavePanel savePanel] beginSheetForDirectory:dir file:nil + modalForWindow:[windowController window] + modalDelegate:self + didEndSelector:@selector(savePanelDidEnd:code:context:) + contextInfo:NULL]; + } else { + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection:NO]; + [panel setAccessoryView:openPanelAccessoryView()]; + + [panel beginSheetForDirectory:dir file:nil types:nil + modalForWindow:[windowController window] + modalDelegate:self + didEndSelector:@selector(savePanelDidEnd:code:context:) + contextInfo:NULL]; + } +} + +- (void)handleShowDialog:(NSDictionary *)attr +{ + if (!isInitialized) return; + + BOOL inDefaultMode = [[[NSRunLoop currentRunLoop] currentMode] + isEqual:NSDefaultRunLoopMode]; + if (!inDefaultMode) { + // Delay call until run loop is in default mode. + [self performSelectorOnMainThread:@selector(handleShowDialog:) + withObject:attr + waitUntilDone:NO + modes:[NSArray arrayWithObject: + NSDefaultRunLoopMode]]; + return; + } + + NSArray *buttonTitles = [attr objectForKey:@"buttonTitles"]; + if (!(buttonTitles && [buttonTitles count])) return; + + int style = [[attr objectForKey:@"alertStyle"] intValue]; + NSString *message = [attr objectForKey:@"messageText"]; + NSString *text = [attr objectForKey:@"informativeText"]; + NSString *textFieldString = [attr objectForKey:@"textFieldString"]; + MMAlert *alert = [[MMAlert alloc] init]; + + // NOTE! This has to be done before setting the informative text. + if (textFieldString) + [alert setTextFieldString:textFieldString]; + + [alert setAlertStyle:style]; + + if (message) { + [alert setMessageText:message]; + } else { + // If no message text is specified 'Alert' is used, which we don't + // want, so set an empty string as message text. + [alert setMessageText:@""]; + } + + if (text) { + [alert setInformativeText:text]; + } else if (textFieldString) { + // Make sure there is always room for the input text field. + [alert setInformativeText:@""]; + } + + unsigned i, count = [buttonTitles count]; + for (i = 0; i < count; ++i) { + NSString *title = [buttonTitles objectAtIndex:i]; + // NOTE: The title of the button may contain the character '&' to + // indicate that the following letter should be the key equivalent + // associated with the button. Extract this letter and lowercase it. + NSString *keyEquivalent = nil; + NSRange hotkeyRange = [title rangeOfString:@"&"]; + if (NSNotFound != hotkeyRange.location) { + if ([title length] > NSMaxRange(hotkeyRange)) { + NSRange keyEquivRange = NSMakeRange(hotkeyRange.location+1, 1); + keyEquivalent = [[title substringWithRange:keyEquivRange] + lowercaseString]; + } + + NSMutableString *string = [NSMutableString stringWithString:title]; + [string deleteCharactersInRange:hotkeyRange]; + title = string; + } + + [alert addButtonWithTitle:title]; + + // Set key equivalent for the button, but only if NSAlert hasn't + // already done so. (Check the documentation for + // - [NSAlert addButtonWithTitle:] to see what key equivalents are + // automatically assigned.) + NSButton *btn = [[alert buttons] lastObject]; + if ([[btn keyEquivalent] length] == 0 && keyEquivalent) { + [btn setKeyEquivalent:keyEquivalent]; + } + } + + [alert beginSheetModalForWindow:[windowController window] + modalDelegate:self + didEndSelector:@selector(alertDidEnd:code:context:) + contextInfo:NULL]; + + [alert release]; +} + + @end // MMVimController (Private) diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index c2d10c59..cac13432 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -182,6 +182,8 @@ enum { FindReplaceMsgID, ActivateKeyScriptID, DeactivateKeyScriptID, + BrowseForFileMsgID, + ShowDialogMsgID, }; diff --git a/src/MacVim/MacVim.m b/src/MacVim/MacVim.m index 17f4e015..93a9d1ba 100644 --- a/src/MacVim/MacVim.m +++ b/src/MacVim/MacVim.m @@ -86,6 +86,8 @@ char *MessageStrings[] = "FindReplaceMsgID", "ActivateKeyScriptID", "DeactivateKeyScriptID", + "BrowseForFileMsgID", + "ShowDialogMsgID", }; -- 2.11.4.GIT