Bug for UI.savepanel - reappearing in SketchUp 2015

Hey, all. In the documentation for UI.savepanel, the following appears:

Bug Fixed in SketchUp 2014: Wildcards were not working properly from SU7 to SU2013. Semicolon-separated lists of wildcards did not populate the file type dropdown. The filter string would be shown in the file name field with ‘*’ characters converted to ‘_’ characters.

I’m noticing this exact issue happening when I call UI.savepanel in SketchUp 2015 on 64-bit Windows.

For clarity, here is the function call:

UI.savepanel("Set File Location", "C:\\", "*.flv;*.mp4;*.mpeg4")

As the fix report states, the wildcards are not appearing in the file type dropdown, but showing in the filename location with underscore characters replacing the asterisks.

I’m calling this function within a UI::WebDialog constructor.

Also, I’m not sure if this is the right place to report bugs - if not, feel free to point me in the right direction and I’d be happy to post this issue there.



Also, for some reason it seems like UI.savepanel does not fully escape the backslashes within the returned filepath.
I just learned that it’s actually valid in Ruby to perform the following:

variable = "C:\some\path\to\dir"

as opposed to

variable = "C:\\some\\path\\to\\dir"

Despite the validity, this isn’t legal in JavaScript, so if the path is sent to the web dialog without any kind of check for this, then JavaScript will omit the back slash characters.

I might be missing something here, but I’m thinking this is also a side effect from calling UI.savepanel.

Edit 2

Also, if the value returned from UI.savepanel is sent to an external C function and read using the Ruby Extension API, the memory read is invalid and a segmentation fault is thrown.

I decided to send a dummy string in order to compare the result, and there were no issues.

Reread the API notes… You specify types to OPEN…

path = UI.openpanel("Open File", "C:\\", "Movie Files|*.flv;*.mp4;*.mpeg4||")

BUT to SAVE the UI.savepanel expects one default file-name or *.filetype, so…

path = UI.savepanel("File Location/Type .flv|.mp4|.mpeg4", "C:\\", "*")

The PC file separator \ can be substituted in Ruby by / with no detriment - making it suitable for use elsewhere - like in Javascript. Ruby methods always use /, but it's clever enough to cope with \. Some of SketchUp's methods [like UI.savepanel ] return a \ path which you need to trap. So use say:
path.tr!("\\", "/")


path.gsub!(/\\/, '/')

or probably the best

path = File.expand_path(path)

which will makes \ into / and expand paths like "~/xxx/yyy"

When entering paths as text use one of these formats:


Inside "" you must escape the \ - it is used as an escape-character in \n, \t etc
All of these 4 paths are OK in Ruby for use on PCs.
The 2 paths using \ are needed in PCs for doing ‘system calls’ [CMD|BAT], VBS usage etc.
The 2 paths using / are needed in Ruby on MACs, in MAC ‘system-calls’, AND in all paths in Javascript, HTML etc.
So you may need to swap back and forth using .tr()

1 Like

What TIG said- in regard to the syntax - and in regard to the \ character which need to be escaped in Ruby.

Do you have some example code here?

[quote=“TIG”]… or probably the best

path = File.expand_path(path)

which will makes \ into / and expand paths like "~/xxx/yyy"

Warning: File.expand_path() is stupid!

b[/b] Although it will expand ~ to the user’s home path, it will do so only on PC, ONLY IF the HOME environment variable is set.

  • SketchUp from 2014 onward now makes sure that ENV["HOME"] is set under Windows, using Ruby’s File::SEPARATOR character (usually the forward slash.).

  • IF you will be relying upon a tilde character to expand within path strings, then for prior versions you should use something like:
    ENV["HOME"] ||= ENV["USERPROFILE"].tr('\\','/')
    which means:
    ENV["HOME"]= ENV["USERPROFILE"].tr('\\','/') unless ENV["HOME"]
    (ie, unset variables, are missing members of the ENV hash, so when no hash key is present, Ruby returns a nil value from a call to the [] method. That causes the unless clause to return false.)

b[/b] Most importantly,… File.expand_path() will stupidly prepend Dir.getwd (the current working directory,) onto ANY path argument or string argument, without checking it’s validity!

  • It is up to YOU (the programmer,) to check that the path (be it file or directory,) actually exists.
path= File.expand_path( "MyModels" )
if Kernel.test(?d,path)
   filepath = UI.savepanel("Save As", path, "SketchUp Model(*.skp)|*.skp||")
 # recover gracefully as the subdir does not exist

This is what is stated for the filename argument of UI.savepanel (the documentation hyperlink in the original post will take you directly to the entry of UI.savepanel):

The default filename for the save panel. On Windows, you can alternatively pass a mask, like “*.txt”, to have all the .txt files display. If you want multiple file types to display, you can supply multiple masks for the filename and separate them with a semicolon, like this: “*.txt;*.doc”.

Nonetheless, using gsub in combination with a single mask extension did in fact solve the issue with the crash; thanks for the help :smile:

However, the issue with the underscore replacing the asterisk, and the filter name being placed in the filename text area (as opposed to the filetype area below it) is still there when the save dialog is shown.

I doubt this will help pinpoint anything, but just in case here’s the call:

UI.savepanel("Set File Location", "c:\\some\\path", "*.flv").gsub(/\\/, '/')

Hi, I believe the old code is still in place so that is someone uses the old syntax, we didn’t break anything for that extension. So since that snippet you posted isn’t using the correct syntax, we take the old, bugged, codepath.

This is the syntax you want. Note: our docs apparently have an issue that they are not accurately displaying the syntax. It took me a few tries to remember how to do it, but this is it I believe.

UI.savepanel("Set File Location", "c:\\some\\path", "*.flv|*.flv|").gsub(/\\/, '/')

Hope that helps!


1 Like

The list of file types are terminated with a double-pipe (which is not Ruby-ish.)