Setting the path for ofSystemSaveDialog()

#1

While writing a save routine for an application I’m developing, I noticed that ofSystemSaveDialog() does not allow me to specify a default path (like ofSystemLoadDialog does).

Since I needed that feature in my app, I created a super easy custom save dialog function; I’m sharing it here, in case someone finds it useful:

ofFileDialogResult customSaveDialog(string defaultName, string messageName, string defaultPath){
    ofFileDialogResult dr;
    
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSSavePanel * saveDialog = [NSSavePanel savePanel];
    
    [saveDialog setMessage:[NSString stringWithUTF8String:messageName.c_str()]];
    
    if(!defaultPath.empty()){
        NSString * s = [NSString stringWithUTF8String:defaultPath.c_str()];
        s = [[s stringByExpandingTildeInPath] stringByResolvingSymlinksInPath];
        NSURL * defaultPathUrl = [NSURL fileURLWithPath:s];
        [saveDialog setDirectoryURL:defaultPathUrl];
    }
    
    [saveDialog setNameFieldStringValue:[NSString stringWithUTF8String:defaultName.c_str()]];
    
    NSInteger buttonClicked = [saveDialog runModal];
    
    NSWindow * appWindow = (NSWindow *)ofGetCocoaWindow();
	if(appWindow) {
		[appWindow makeKeyAndOrderFront:nil];
	}
    
    if(buttonClicked==NSFileHandlingPanelOKButton){
        dr.filePath = string([[[saveDialog URL] path] UTF8String]);
    }
    [pool drain];
    
     if( dr.filePath.length() > 0 ){
	dr.bSuccess = true;
	dr.fileName = ofFilePath::getFileName(dr.filePath);
    }

    return dr;
}
#2

This is one of the thinks that i was looking for.

Where do i paste this function? It has lots of objects and things that are not being recognized

#3

Hey,
you can basically have this function anywhere in your code, just keep in mind that:

  • it’s OS X only; if you need the same functionality for Linux or Win, you’ll need to interface with the OS specific way of serving you a save dialog.
  • like a lot of OS X specific stuff, it includes some (eeek! gross!) Objective C. You can mix C++ and Objective C in the same project and even in the same source code file: it’s called Objective C++ (I know man, it’s so decadent it sounds like a joke :slight_smile: ) and you just need to let XCode know that a specific source code file should be compiled as “Objective C++” by using the .mm extension, instead of .cpp. (go here if you want to dig deeper)
  • in the code I included in my original post I did not specify any scope for the function; if you keep your function out of any class (i.e. you paste it in a dedicated source file) you can leave it like this, but if you make it part of a class of yours (i.e. you add it to ofApp), your implementation should include the class scope; for example in YourClass.h you’d make a prototype like:
class YourClass{
...
ofFileDialogResult customSaveDialog(string defaultName, string messageName, string defaultPath);
...
}

and in YourClass.mm you’d have:

ofFileDialogResult YourClass::customSaveDialog(string defaultName, string messageName, string defaultPath){
...
}