/** * @file llfilepicker_mac.cpp * @brief OS-specific file picker * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifdef LL_DARWIN #import #import #include #include "llfilepicker_mac.h" // Convert a file extension or UTI string into a UTType for use with // NSOpenPanel/NSSavePanel's allowedContentTypes. static UTType *contentTypeForString(NSString *typeString) { UTType *type = [UTType typeWithFilenameExtension:typeString]; if (!type) { type = [UTType typeWithIdentifier:typeString]; } return type; } NSOpenPanel *init_panel(const std::vector* allowed_types, unsigned int flags) { int i; NSOpenPanel *panel = [NSOpenPanel openPanel]; NSMutableArray *fileTypes = nil; if ( allowed_types && !allowed_types->empty()) { fileTypes = [[NSMutableArray alloc] init]; for (i=0;isize();++i) { NSString *typeString = [NSString stringWithCString:(*allowed_types)[i].c_str() encoding:[NSString defaultCStringEncoding]]; UTType *type = contentTypeForString(typeString); if (type) { [fileTypes addObject:type]; } } } //[panel setMessage:@"Import one or more files or directories."]; [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ]; [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ]; [panel setCanCreateDirectories: true]; [panel setResolvesAliases: true]; [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )]; [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; if (fileTypes && fileTypes.count > 0) { [panel setAllowedContentTypes:fileTypes]; } else { // I suggest it's better to open the last path and let this default to home dir as necessary // for consistency with other OS X apps // //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ]; } return panel; } std::unique_ptr> doLoadDialog(const std::vector* allowed_types, unsigned int flags) { std::unique_ptr> outfiles; @autoreleasepool { int result; //Aura TODO: We could init a small window and release it at the end of this routine //for a modeless interface. NSOpenPanel *panel = init_panel(allowed_types,flags); result = [panel runModal]; if (result == NSModalResponseOK) { NSArray *filesToOpen = [panel URLs]; int i, count = [filesToOpen count]; if (count > 0) { outfiles.reset(new std::vector); } for (i=0; ipush_back(afilestr); } } } return outfiles; } void doLoadDialogModeless(const std::vector* allowed_types, unsigned int flags, void (*callback)(bool, std::vector &, void*), void *userdata) { @autoreleasepool { NSOpenPanel *panel = init_panel(allowed_types,flags); NSWindow *mainWindow = [NSApp mainWindow]; if (mainWindow) { [panel beginSheetModalForWindow:mainWindow completionHandler:^(NSModalResponse result) { std::vector outfiles; if (result == NSModalResponseOK) { NSArray *filesToOpen = [panel URLs]; int i, count = [filesToOpen count]; if (count > 0) { for (i=0; i outfiles; if (result == NSModalResponseOK) { NSArray *filesToOpen = [panel URLs]; int i, count = [filesToOpen count]; if (count > 0) { for (i=0; i doSaveDialog(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, unsigned int flags) { std::unique_ptr outfile; @autoreleasepool { NSSavePanel *panel = [NSSavePanel savePanel]; NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]]; NSArray *extensions = [extensionns componentsSeparatedByString:@","]; NSMutableArray *fileType = [[NSMutableArray alloc] init]; for (NSString *ext in extensions) { UTType *type = contentTypeForString(ext); if (type) { [fileType addObject:type]; } } //[panel setMessage:@"Save Image File"]; [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; [panel setCanSelectHiddenExtension:true]; if (fileType.count > 0) { [panel setAllowedContentTypes:fileType]; } NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; NSURL* url = [NSURL fileURLWithPath:fileName]; [panel setNameFieldStringValue: fileName]; [panel setDirectoryURL: url]; if([panel runModal] == NSModalResponseOK) { NSURL* url = [panel URL]; NSString* p = [url path]; outfile.reset(new std::string([p UTF8String])); // write the file } } return outfile; } void doSaveDialogModeless(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, unsigned int flags, void (*callback)(bool, std::string&, void*), void *userdata) { @autoreleasepool { NSSavePanel *panel = [NSSavePanel savePanel]; NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]]; NSArray *extensions = [extensionns componentsSeparatedByString:@","]; NSMutableArray *fileType = [[NSMutableArray alloc] init]; for (NSString *ext in extensions) { UTType *type = contentTypeForString(ext); if (type) { [fileType addObject:type]; } } //[panel setMessage:@"Save Image File"]; [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; [panel setCanSelectHiddenExtension:true]; if (fileType.count > 0) { [panel setAllowedContentTypes:fileType]; } NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; NSURL* url = [NSURL fileURLWithPath:fileName]; [panel setNameFieldStringValue: fileName]; NSURL *last_url = [[NSUserDefaults standardUserDefaults] URLForKey:@"NSNavLastRootDirectory"]; if(!last_url) { NSURL *downloads_url = [[NSFileManager defaultManager] URLsForDirectory:NSDownloadsDirectory inDomains:NSUserDomainMask].firstObject; [panel setDirectoryURL:downloads_url]; } [panel beginWithCompletionHandler:^(NSModalResponse result) { if (result == NSModalResponseOK) { NSURL* url = [panel URL]; NSString* p = [url path]; std::string outfile([p UTF8String]); callback(true, outfile, userdata); } else // cancel { std::string outfile; callback(false, outfile, userdata); } }]; } } #endif