diff options
author | fvogel <fvogelnew1@free.fr> | 2017-06-05 18:32:24 (GMT) |
---|---|---|
committer | fvogel <fvogelnew1@free.fr> | 2017-06-05 18:32:24 (GMT) |
commit | fbac4859a673c9a5f0c8936ed8d18ea9e9145304 (patch) | |
tree | 4e184d638205d9ce2ef854ebea9393e5d8d91bd3 /macosx/tkMacOSXDialog.c | |
parent | 452ee6a6849e04a6a94bc7488e935129614041f8 (diff) | |
parent | fd3fd3d844d9ff5f83c3fd26ee88f2c02892c180 (diff) | |
download | tk-fbac4859a673c9a5f0c8936ed8d18ea9e9145304.zip tk-fbac4859a673c9a5f0c8936ed8d18ea9e9145304.tar.gz tk-fbac4859a673c9a5f0c8936ed8d18ea9e9145304.tar.bz2 |
merge trunk
Diffstat (limited to 'macosx/tkMacOSXDialog.c')
-rw-r--r-- | macosx/tkMacOSXDialog.c | 555 |
1 files changed, 372 insertions, 183 deletions
diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index 80a7a11..3397f71 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -6,6 +6,7 @@ * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> + * Copyright (c) 2017 Christian Gollwitzer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -24,6 +25,22 @@ #define modalOther -1 #define modalError -2 +/*Vars for filtering in "open file" and "save file" dialogs.*/ +typedef struct { + bool doFileTypes; // show the accessory view which displays the filter menu + bool preselectFilter; // a filter was selected by the typevariable + bool userHasSelectedFilter; // The user has changed the filter in the accessory view + NSMutableArray *fileTypeNames; // array of names, e.g. "Text document" + NSMutableArray *fileTypeExtensions; // array of allowed extensions per name, e.g. "txt", "doc" + NSMutableArray *fileTypeLabels; // displayed string, e.g. "Text document (.txt, .doc)" + NSMutableArray *allAllowedExtensions; // set of all allowed extensions + NSInteger fileTypeIndex; // index of currently selected filter +} filepanelFilterInfo; + +filepanelFilterInfo filterInfo; + +NSOpenPanel *openpanel; +NSSavePanel *savepanel; static const char *const colorOptionStrings[] = { "-initialcolor", "-parent", "-title", NULL @@ -142,22 +159,6 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = { [TYPE_YESNOCANCEL] = {5, 6, 4}, }; -/* - * Construct a file URL from directory and filename. Either may - * be nil. If both are nil, returns nil. - */ -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1050 -static NSURL *getFileURL(NSString *directory, NSString *filename) { - NSURL *url = nil; - if (directory) { - url = [NSURL fileURLWithPath:directory]; - } - if (filename) { - url = [NSURL URLWithString:filename relativeToURL:url]; - } - return url; -} -#endif #pragma mark TKApplication(TKDialog) @@ -212,6 +213,7 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { } } + - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo { @@ -247,6 +249,23 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { ckfree(callbackInfo); } } + +- (void)selectFormat:(id)sender { + NSPopUpButton *button = (NSPopUpButton *)sender; + filterInfo.fileTypeIndex = [button indexOfSelectedItem]; + NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]; + [openpanel setAllowedFileTypes:allowedtypes]; + filterInfo.userHasSelectedFilter = true; + +} + +- (void)saveFormat:(id)sender { + NSPopUpButton *button = (NSPopUpButton *)sender; + filterInfo.fileTypeIndex = [button indexOfSelectedItem]; + NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]; + [savepanel setAllowedFileTypes:allowedtypes]; +} + @end #pragma mark - @@ -360,6 +379,98 @@ Tk_ChooseColorObjCmd( end: return result; } + +/* dissect the -filetype nested lists and store the information + * in the filterInfo structure */ +int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVariablePtr) { + + if (!fileTypesPtr) { + filterInfo.doFileTypes = false; + return TCL_OK; + } + + FileFilterList fl; + TkInitFileFilters(&fl); + if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) { + TkFreeFileFilters(&fl); + return TCL_ERROR; + } + + filterInfo.doFileTypes = (fl.filters != NULL); + + filterInfo.fileTypeIndex = 0; + filterInfo.fileTypeExtensions = [NSMutableArray array]; + filterInfo.fileTypeNames = [NSMutableArray array]; + filterInfo.fileTypeLabels = [NSMutableArray array]; + filterInfo.allAllowedExtensions = [NSMutableArray array]; + + if (filterInfo.doFileTypes) { + for (FileFilter *filterPtr = fl.filters; filterPtr; + filterPtr = filterPtr->next) { + NSString * name = [[NSString alloc] initWithUTF8String: filterPtr -> name]; + [filterInfo.fileTypeNames addObject:name]; + [name release]; + NSMutableArray * clauseextensions = [NSMutableArray array]; + NSMutableArray * displayextensions = [NSMutableArray array]; + + for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; + clausePtr = clausePtr->next) { + for (GlobPattern *globPtr = clausePtr->patterns; globPtr; + globPtr = globPtr->next) { + const char *str = globPtr->pattern; + while (*str && (*str == '*' || *str == '.')) { + str++; + } + if (*str) { + NSString *extension = [[NSString alloc] initWithUTF8String:str]; + if (![filterInfo.allAllowedExtensions containsObject:extension]) { + [filterInfo.allAllowedExtensions addObject:extension]; + } + + [clauseextensions addObject:extension]; + [displayextensions addObject:[@"." stringByAppendingString:extension]]; + + [extension release]; + } + } + } + [filterInfo.fileTypeExtensions addObject:clauseextensions]; + + NSMutableString * label = [[NSMutableString alloc] initWithString:name]; + [label appendString:@" ("]; + [label appendString:[displayextensions componentsJoinedByString:@", "]]; + [label appendString:@")"]; + [filterInfo.fileTypeLabels addObject:label]; + [label release]; + + } + + /* Check if the typevariable exists and matches one of the names */ + filterInfo.preselectFilter = false; + filterInfo.userHasSelectedFilter = false; + if (typeVariablePtr) { + /* extract the variable content as a NSString */ + Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, typeVariablePtr, NULL, TCL_GLOBAL_ONLY); + + /* check that the typevariable exists */ + if (selectedFileTypeObj != NULL) { + const char *selectedFileType = Tcl_GetString(selectedFileTypeObj); + NSString *selectedFileTypeStr = [[NSString alloc] initWithUTF8String:selectedFileType]; + NSUInteger index = [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr]; + + if (index != NSNotFound) { + filterInfo.fileTypeIndex = index; + filterInfo.preselectFilter = true; + } + } + } + + } + + TkFreeFileFilters(&fl); + return TCL_OK; +} + /* *---------------------------------------------------------------------- @@ -388,19 +499,16 @@ Tk_GetOpenFileObjCmd( char *str; int i, result = TCL_ERROR, haveParentOption = 0; int index, len, multiple = 0; - FileFilterList fl; - Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL; + Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL; FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; NSString *directory = nil, *filename = nil; - NSString *message, *title, *type; + NSString *message = nil, *title = nil; NSWindow *parent; - NSMutableArray *fileTypes = nil; - NSOpenPanel *panel = [NSOpenPanel openPanel]; + openpanel = [NSOpenPanel openPanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; - TkInitFileFilters(&fl); for (i = 1; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings, sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { @@ -416,9 +524,7 @@ Tk_GetOpenFileObjCmd( case OPEN_DEFAULT: break; case OPEN_FILETYPES: - if (TkGetFileFilters(interp, &fl, objv[i + 1], 0) != TCL_OK) { - goto end; - } + fileTypesPtr = objv[i + 1]; break; case OPEN_INITDIR: str = Tcl_GetStringFromObj(objv[i + 1], &len); @@ -432,13 +538,12 @@ Tk_GetOpenFileObjCmd( if (len) { filename = [[[NSString alloc] initWithUTF8String:str] autorelease]; + [openpanel setNameFieldStringValue:filename]; } break; case OPEN_MESSAGE: message = [[NSString alloc] initWithUTF8String: Tcl_GetString(objv[i + 1])]; - [panel setMessage:message]; - [message release]; break; case OPEN_MULTIPLE: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], @@ -457,8 +562,6 @@ Tk_GetOpenFileObjCmd( case OPEN_TITLE: title = [[NSString alloc] initWithUTF8String: Tcl_GetString(objv[i + 1])]; - [panel setTitle:title]; - [title release]; break; case OPEN_TYPEVARIABLE: typeVariablePtr = objv[i + 1]; @@ -468,40 +571,70 @@ Tk_GetOpenFileObjCmd( break; } } - [panel setAllowsMultipleSelection:multiple]; - if (fl.filters) { - fileTypes = [NSMutableArray array]; - for (FileFilter *filterPtr = fl.filters; filterPtr; - filterPtr = filterPtr->next) { - for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; - clausePtr = clausePtr->next) { - for (GlobPattern *globPtr = clausePtr->patterns; globPtr; - globPtr = globPtr->next) { - str = globPtr->pattern; - while (*str && (*str == '*' || *str == '.')) { - str++; - } - if (*str) { - type = [[NSString alloc] initWithUTF8String:str]; - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; - } - [type release]; - } - } - for (MacFileType *mfPtr = clausePtr->macTypes; mfPtr; - mfPtr = mfPtr->next) { - if (mfPtr->type) { - type = NSFileTypeForHFSTypeCode(mfPtr->type); - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; - } - } - } - } + + /* From OSX 10.11, the title string is silently ignored. + * Prepend the title to the message + * NOTE should be conditional on OSX version, but + * -mmacosx-version-min does not revert this behaviour*/ + if (title) { + [openpanel setTitle:title]; + if (message) { + NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; + [message release]; + [title release]; + message = fullmessage; + } else { + message = title; + } + } + + if (message) { + [openpanel setMessage:message]; + [message release]; + } + + [openpanel setAllowsMultipleSelection:multiple]; + + if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) { + goto end; + } + + if (filterInfo.doFileTypes) { + NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)]; + NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; + [label setStringValue:@"Enable:"]; + [label setBordered:NO]; + [label setBezeled:NO]; + [label setDrawsBackground:NO]; + + NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; + [popupButton setAction:@selector(selectFormat:)]; + + [accessoryView addSubview:label]; + [accessoryView addSubview:popupButton]; + + if (filterInfo.preselectFilter) { + /* A specific filter was selected from the typevariable. Select it and + * open the accessory view */ + [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; + /* on OSX > 10.11, the optons are not visible by default. Ergo allow all file types + [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]]; + */ + [openpanel setAllowedFileTypes:filterInfo.allAllowedExtensions]; + } else { + [openpanel setAllowedFileTypes:filterInfo.allAllowedExtensions]; } + + [openpanel setAllowsOtherFileTypes:NO]; + + [openpanel setAccessoryView:accessoryView]; + } else { + /* No filters are given. Allow picking all files */ + [openpanel setAllowsOtherFileTypes:YES]; } - [panel setAllowedFileTypes:fileTypes]; + if (cmdObj) { callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { @@ -509,6 +642,7 @@ Tk_GetOpenFileObjCmd( } Tcl_IncrRefCount(cmdObj); } + callbackInfo->cmdObj = cmdObj; callbackInfo->interp = interp; callbackInfo->multiple = multiple; @@ -516,52 +650,63 @@ Tk_GetOpenFileObjCmd( if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - [panel beginSheetForDirectory:directory + [openpanel beginSheetForDirectory:directory file:filename - types:fileTypes + types:openFileTypes modalForWindow:parent modalDelegate:NSApp didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setAllowedFileTypes:fileTypes]; - [panel setDirectoryURL:getFileURL(directory, filename)]; - [panel beginSheetModalForWindow:parent + if (directory) { + [openpanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [openpanel setNameFieldStringValue:filename]; + [openpanel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel + { [NSApp tkFilePanelDidEnd:openpanel returnCode:returnCode contextInfo:callbackInfo ]; } ]; #endif - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - modalReturnCode = [panel runModalForDirectory:directory + modalReturnCode = [openpanel runModalForDirectory:directory file:filename]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - modalReturnCode = [panel runModal]; + if (directory) { + [openpanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [openpanel setNameFieldStringValue:filename]; + modalReturnCode = [openpanel runModal]; #endif - [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode + [NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode contextInfo:callbackInfo]; } result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (parentIsKey) { [parent makeKeyWindow]; } - if (typeVariablePtr && result == TCL_OK) { + + if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && + filterInfo.doFileTypes && filterInfo.userHasSelectedFilter) { /* - * The -typevariable option is not really supported. + * The -typevariable must be set to the selected file type, if the dialog was not cancelled */ - - Tcl_SetVar2(interp, Tcl_GetString(typeVariablePtr), NULL, - "", TCL_GLOBAL_ONLY); + #if 0 + NSLog(@"result: %i modal: %li", result, (long)modalReturnCode); + #endif + NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex]; + Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, + Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); } + end: - TkFreeFileFilters(&fl); return result; } + /* *---------------------------------------------------------------------- @@ -591,19 +736,16 @@ Tk_GetSaveFileObjCmd( int i, result = TCL_ERROR, haveParentOption = 0; int confirmOverwrite = 1; int index, len; - FileFilterList fl; - Tcl_Obj *cmdObj = NULL; + Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL; FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; NSString *directory = nil, *filename = nil, *defaultType = nil; - NSString *message, *title, *type; + NSString *message = nil, *title = nil; NSWindow *parent; - NSMutableArray *fileTypes = nil; - NSSavePanel *panel = [NSSavePanel savePanel]; + savepanel = [NSSavePanel savePanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; - TkInitFileFilters(&fl); for (i = 1; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings, sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { @@ -616,96 +758,120 @@ Tk_GetSaveFileObjCmd( goto end; } switch (index) { - case SAVE_DEFAULT: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - while (*str && (*str == '*' || *str == '.')) { - str++; - } - if (*str) { - defaultType = [[[NSString alloc] initWithUTF8String:str] - autorelease]; - } - break; - case SAVE_FILETYPES: - if (TkGetFileFilters(interp, &fl, objv[i + 1], 0) != TCL_OK) { - goto end; - } - break; - case SAVE_INITDIR: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - if (len) { - directory = [[[NSString alloc] initWithUTF8String:str] - autorelease]; - } - break; - case SAVE_INITFILE: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - if (len) { - filename = [[[NSString alloc] initWithUTF8String:str] - autorelease]; - } - break; - case SAVE_MESSAGE: - message = [[NSString alloc] initWithUTF8String: - Tcl_GetString(objv[i + 1])]; - [panel setMessage:message]; + case SAVE_DEFAULT: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + while (*str && (*str == '*' || *str == '.')) { + str++; + } + if (*str) { + defaultType = [[[NSString alloc] initWithUTF8String:str] + autorelease]; + } + break; + case SAVE_FILETYPES: + fileTypesPtr = objv[i + 1]; + break; + case SAVE_INITDIR: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + if (len) { + directory = [[[NSString alloc] initWithUTF8String:str] + autorelease]; + } + break; + case SAVE_INITFILE: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + if (len) { + filename = [[[NSString alloc] initWithUTF8String:str] + autorelease]; + [savepanel setNameFieldStringValue:filename]; + } + break; + case SAVE_MESSAGE: + message = [[NSString alloc] initWithUTF8String: + Tcl_GetString(objv[i + 1])]; + break; + case SAVE_PARENT: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + tkwin = Tk_NameToWindow(interp, str, tkwin); + if (!tkwin) { + goto end; + } + haveParentOption = 1; + break; + case SAVE_TITLE: + title = [[NSString alloc] initWithUTF8String: + Tcl_GetString(objv[i + 1])]; + break; + case SAVE_TYPEVARIABLE: + typeVariablePtr = objv[i + 1]; + break; + case SAVE_COMMAND: + cmdObj = objv[i+1]; + break; + case SAVE_CONFIRMOW: + if (Tcl_GetBooleanFromObj(interp, objv[i + 1], + &confirmOverwrite) != TCL_OK) { + goto end; + } + break; + } + } + + if (title) { + [savepanel setTitle:title]; + if (message) { + NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; [message release]; - break; - case SAVE_PARENT: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - tkwin = Tk_NameToWindow(interp, str, tkwin); - if (!tkwin) { - goto end; - } - haveParentOption = 1; - break; - case SAVE_TITLE: - title = [[NSString alloc] initWithUTF8String: - Tcl_GetString(objv[i + 1])]; - [panel setTitle:title]; [title release]; - break; - case SAVE_TYPEVARIABLE: - break; - case SAVE_COMMAND: - cmdObj = objv[i+1]; - break; - case SAVE_CONFIRMOW: - if (Tcl_GetBooleanFromObj(interp, objv[i + 1], - &confirmOverwrite) != TCL_OK) { - goto end; - } - break; + message = fullmessage; + } else { + message = title; } } - if (fl.filters || defaultType) { - fileTypes = [NSMutableArray array]; - [fileTypes addObject:defaultType ? defaultType : (id)kUTTypeContent]; - for (FileFilter *filterPtr = fl.filters; filterPtr; - filterPtr = filterPtr->next) { - for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; - clausePtr = clausePtr->next) { - for (GlobPattern *globPtr = clausePtr->patterns; globPtr; - globPtr = globPtr->next) { - str = globPtr->pattern; - while (*str && (*str == '*' || *str == '.')) { - str++; - } - if (*str) { - type = [[NSString alloc] initWithUTF8String:str]; - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; - } - [type release]; - } - } - } - } - [panel setAllowedFileTypes:fileTypes]; - [panel setAllowsOtherFileTypes:YES]; + + if (message) { + [savepanel setMessage:message]; + [message release]; + } + + if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) { + goto end; } - [panel setCanSelectHiddenExtension:YES]; - [panel setExtensionHidden:NO]; + + if (filterInfo.doFileTypes) { + NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)]; + NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; + [label setStringValue:NSLocalizedString(@"Format:", nil)]; + [label setBordered:NO]; + [label setBezeled:NO]; + [label setDrawsBackground:NO]; + + NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; + [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; + [popupButton setAction:@selector(saveFormat:)]; + + [accessoryView addSubview:label]; + [accessoryView addSubview:popupButton]; + + [savepanel setAccessoryView:accessoryView]; + + [savepanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]]; + [savepanel setAllowsOtherFileTypes:NO]; + } else if (defaultType) { + /* If no filetypes are given, defaultextension is an alternative way + * to specify the attached extension. Just propose this extension, + * but don't display an accessory view */ + NSMutableArray *AllowedFileTypes = [NSMutableArray array]; + [AllowedFileTypes addObject:defaultType]; + [savepanel setAllowedFileTypes:AllowedFileTypes]; + [savepanel setAllowsOtherFileTypes:YES]; + } + + [savepanel setCanSelectHiddenExtension:YES]; + [savepanel setExtensionHidden:NO]; + if (cmdObj) { callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { @@ -716,11 +882,12 @@ Tk_GetSaveFileObjCmd( callbackInfo->cmdObj = cmdObj; callbackInfo->interp = interp; callbackInfo->multiple = 0; + parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - [panel beginSheetForDirectory:directory + [savepanel beginSheetForDirectory:directory file:filename modalForWindow:parent modalDelegate:NSApp @@ -728,30 +895,52 @@ Tk_GetSaveFileObjCmd( @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - [panel beginSheetModalForWindow:parent + if (directory) { + [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [savepanel setNameFieldStringValue:filename]; + [savepanel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel + { [NSApp tkFilePanelDidEnd:savepanel returnCode:returnCode contextInfo:callbackInfo ]; } ]; #endif - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:savepanel]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - modalReturnCode = [panel runModalForDirectory:directory file:filename]; + modalReturnCode = [savepanel runModalForDirectory:directory file:filename]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - modalReturnCode = [panel runModal]; + if (directory) { + [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [savepanel setNameFieldStringValue:filename]; + modalReturnCode = [savepanel runModal]; + #if 0 + NSLog(@"modal: %li", modalReturnCode); + #endif #endif - [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode + [NSApp tkFilePanelDidEnd:savepanel returnCode:modalReturnCode contextInfo:callbackInfo]; } result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (parentIsKey) { [parent makeKeyWindow]; } + + if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) { + /* + * The -typevariable must be set to the selected file type, if the dialog was not cancelled + */ + #if 0 + NSLog(@"result: %i modal: %li", result, (long)modalReturnCode); + #endif + NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex]; + Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, + Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); + } + + end: - TkFreeFileFilters(&fl); return result; } @@ -787,7 +976,7 @@ Tk_ChooseDirectoryObjCmd( Tcl_Obj *cmdObj = NULL; FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; - NSString *directory = nil, *filename = nil; + NSString *directory = nil; NSString *message, *title; NSWindow *parent; NSOpenPanel *panel = [NSOpenPanel openPanel]; @@ -863,13 +1052,13 @@ Tk_ChooseDirectoryObjCmd( parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 [panel beginSheetForDirectory:directory - file:filename + file:nil modalForWindow:parent modalDelegate:NSApp didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; [panel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) { [NSApp tkFilePanelDidEnd:panel @@ -881,7 +1070,7 @@ Tk_ChooseDirectoryObjCmd( #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 modalReturnCode = [panel runModalForDirectory:directory file:nil]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; modalReturnCode = [panel runModal]; #endif [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode |