Setting the path for ofSystemSaveDialog()

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;
}

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

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){
...
}