Good default directory for UI.savepanel()?


#1

My extension lets the user save out a file, but is there a recommended (cross-platform) directory path to use by default? Perhaps something like ENV['HOME'] ?

I’m currently using "c:\\" which certainly works (at least on Windows), and is used as the example in the API docs: UI.savepanel().

Thanks


#2

SketchUp will set ENV['HOME'] on most recent PC versions of SketchUp (perhaps 2013 and higher) so that Ruby can expand the tilde in path strings using the contents of that environment variable. Ie:

path = File.expand_path("~/Documents")
#=> C:/Users/Dan/Documents

ENV['HOME'] is always set on Mac. But you can use a backup OR clause that will work on Windows to give you the user’s home path in the event that ENV['HOME'] is not set:

home = ENV["HOME"] || ENV["USERPROFILE"]

Or you could do:

ENV["HOME"]= ENV["USERPROFILE"] unless ENV["HOME"]

or for Ruby 2.x and higher:

ENV["HOME"]= Dir::home unless ENV["HOME"]

Default Working Directory.

SketchUp sets this to the user’s “Documents” directory in most recent versions.

To see what it is at anytime call standard Ruby class Dir methods:

Dir::pwd

or it’s alias:

Dir::getwd

Never rely upon the current working directory to be anything specific. (Some coders forget to reset it.)

So use the block form of the Dir::chdir method thus:

Dir::chdir(some_absolute_path) {|path|
  # code to execute in the path directory
}
# previous working directory is automatically restored

#3

Windows MRU paths.

On Windows the UI::savepanel and UI::openpanel methods use Microsoft the common dialog library. This library has MRU (Most Recently Used) path defaults per user, for all previous file extensions (including "*.*").

So, you can just use a path like "*.skp" and the openpanel will open to where the user last saved or opened that kind of file.

This is a Windows default and wasn’t really considered much when the methods were written for the API. The methods have changed a bit over time, and this built-in MRU functionality sometime does not work as expected. (Especially with the newer PC only 3rd argument filters.)

So test thoroughly.


#4

Many thanks!

Just to make the issue even more confusing, I’ve just tried a directory of nil and it seems to give a good default on both Sketchup 2013 and 2017 (on Windows). Once a file has been saved once, it switches to the Most Recently Used directory, which is the behaviour I want.

Do you know what nil will do on a Mac?


#5

I do not, but I think Mac does not have this built-in MRU paths saved in their plists.
Macs use a different OSX specific finder dialog I believe.

@slbaumgartner, can you enlighten us ?


I suppose you could mimic the Windows MRU saving behavior for Mac editions of your plugin(s).

See the module methods:

Default keys need to be author+namespace qualified just as modules and attribute dictionaries names need be.
Ex: "SheffieldTech_NiftyPlugin" default settings key for an extension operating within namespace SheffieldTech::NiftyPlugin.

I often use a statement like the following near the top of my plugin sub-module’s code to generate the settings key:

defkey = Module::nesting[0].name.gsub('::','_')

Before using any path (ie, as an argument to the UI::openpanel method, etc.,) verify it exists and is readable using the appropriate methods of the Ruby core File class. (Ie, users have been known to manually delete things, and move folders around, rename folders, when the application is not running.) Ie, code defensively.


#6

On a Mac, using nil for the directory will cause openpanel and savepanel to use the same folder as the last invocation. If the user navigates to another directory to select something, that directory will be used again when nil is passed, even if the user cancelled the last dialog. This last used directory is saved somewhere in the system (I haven’t checked where as it doesn’t really matter) and it will be used again the next time you run SketchUp. In other words, it does not reset per-session to something like your home directory or other hard-wired default.

There are additional Mac quirks/bugs that are not mentioned in the API documentation. As with many other (ahem) “features” of the Mac SU implementation, these were things done by the SU developers, they are not universal to OS X or required by the Mac GUI style:

UI.openpanel ignores the title argument. There isn’t even a place in the dialog for a title to appear. It also doesn’t support wildcard patterns for the filename and there is no place for a selection list to appear anyway. In fact, the filename argument appears to have no effect at all; it isn’t pre-selected and the user can choose anything. This seems harmless, as the method just returns a path, it doesn’t actually open anything, but lack of filters means you have to verify what file type the user selected.

UI.savepanel does display the title at the top of the dialog. If you pass a filename, it will be seeded as the initial value in the “Save As” field. Wildcards are not accepted, in fact they will cause the dialog to hang without displaying! If a file with that name already exists in the selected directory, you will get a “file already exists, overwrite?” dialog - even though no overwrite will actually happen! And again, for lack of filters you can’t prevent the user from choosing or entering a filetype that you don’t know how to save.


#7

Many thanks @slbaumgartner and @DanRathbun. Sounds like just using nil for the directory argument will give a good result on both Windows and Macs :slight_smile: