Dialog Commands¶
Scripting can present various dialogs to request user input, including information, warning, confirmation, yes/no/all/ cancel, file open, file save and directory dialogs. These are all handled through the dialog series of commands.
Overview¶
The dialog commands are executed in the following order to create, present and obtain the result of a dialog.
dialog.setup defines the kind of dialog you want to create
Other dialog commands are executed to set the title, file format, help URL, etc.
dialog.open opens the dialog and presents it to the user. The command blocks until the user dismisses the dialog.
dialog.result returns the user’s choice.
The first step to creating any dialog is to call ‘’’dialog.setup’’’. This determines the dialog type.
1 2 3 | dialog.setup style:{info|warning|error|okCancel|yesNo|
yesNoCancel|yesNoAll|yesNoToAll|saveOK|
fileOpen|fileOpenMulti|fileSave|dir}
|
‘’’info’’, warning’ and error styles display notification dialogs with a single OK button.
okCancel and yesNo style dialogs have two buttons, and are used for simple confirmations.
‘’’yesNoCancel’’’, ‘’’yesNoAll’’’, and yesNoToAll dialogs provide confirm/abort capability for loops.
saveOK dialogs are used to confirm that a save should be performed, such as when saving over a file or quitting without saving.
fileOpen dialogs are used to choose a single file from a system file dialog .
fileOpenMulti dialogs are used to choose one or more files from a system file dialog.
fileSave dialogs are used to choose a location to save a file from a system file dialog .
dir dialogs are used to choose a directory from a system directory dialog .
Creating a Yes/No Dialog: dialog.setup¶
A yesNo dialog has two buttons labeled Yes and ‘’No’’. To create a one, we might use this command:
1 | dialog.setup yesNo
|
Title¶
The dialog.title command lets you set the string that appears in the dialog’s title bar.
1 | dialog.title "Confirm Operation"
|
The title can be a simple static string, or it can be obtained from a Message Tables stored in a config. Message table lookups use the format @table@msg@ for a dictionary lookup, or @table@@id@ for an integer ID lookup. Using message tables allows the interface to be translated for different languages without editing the script or plug-in itself.
Body Text¶
To set the body of the dialog, we use ‘’dialog.msg’’. Again, the message can be either a static string or a message table lookup as described above.
1 | dialog.msg "Perform the operation?"
|
Message Tables and Substitutions¶
Message table strings may have arguments in the form of ‘’%1’’, ‘’%2’’, etc. These can be set with ‘’’dialog.msgArg’’’, which takes the argument number, the datatype and the value to set it to.
1 2 | dialog.msg "@table@msg@"
dialog.msgArg 1 string "test"
|
Help URLs¶
A help URL can also be included in the dialog through ‘’’dialog.helpURL’’’. This normal points to a help file on the local system, but can be any valid URL. When set, a ? button will appear in the dialog, and clicking it will go to that URL.
1 | <nowiki>dialog.helpURL "http://www.google.com"</nowiki>
|
Default Result¶
As with any dialog, these dialogs can be suppressed by the caller of your script or plug-in. A default result can be set for the dialog in case that happens. For files and directories, this will also be displayed as the path when dialog is displayed. The ‘dialog.result command is used to both set the default value and to read out a new value. This does not need to be called for information dialogs, as they have only one button and thus always return ok.
Text hints can be used when setting or reading ‘’’dialog.result’’’’s value. This can be one of ‘’cancel’’, ‘’no’’, ‘’ok’’, ‘’yesToAll’’, or ‘’noToAll’’. The hint yes can be used as a synonym for ok when setting the default value, but ok will always be returned as both resolve to the same integer. Be careful when working with yesNo and okCancel dialogs, as while yes and ok are both the same value, no and cancel are not.
1 | dialog.result ok
|
Dialog Result Codes Table¶
Here’s a table of the possible dialog result codes from the informational dialogs.
Dialog Type |
Dialog Name/Buttons |
Result = “cancel” |
Result = “no” |
Result = “ok” |
Result = “yesToAll” |
Result = “noToAll” |
---|---|---|---|---|---|---|
info |
Info (OK only) |
(none) |
(none) |
OK |
(none) |
(none) |
warning |
Warning (OK only) |
(none) |
(none) |
OK |
(none) |
(none) |
error |
Error (OK only) |
(none) |
(none) |
OK |
(none) |
(none) |
okCancel |
OK/Cancel |
Cancel |
(none) |
OK |
(none) |
(none) |
yesCancel |
Yes/No |
(none) |
No |
Yes |
(none) |
(none) |
saveOK |
Save/Don’t Save/Cancel |
Cancel |
Don’t Save |
Save |
(none) |
(none) |
yesCancel |
Yes/No |
Cancel |
No |
Yes |
(none) |
(none) |
yesNoAll |
Yes/No/Yes To All/No To All |
(none) |
No |
Yes |
Yes To All |
No To All |
yesNoToAll |
Yes/No/Yes To All/No To All |
Cancel |
No |
Yes |
(none) |
No To All |
Displaying the Dialog¶
Now that all the dialog information is set, it can be presented with a call to ‘’’dialog.open’’’.
1 | dialog.open
|
‘’dialog.open’’ will block until the user has made a choice.
Note that the dailog.open command fails with an abort code if the user hits a no or cancel style button. In Perl]] and [[Lua]] you can simply ignore the error code, but in [[Python this will throw an exception, which you will need to catch and optionally ignore, This behavior allows the command to be more generally tested for success or failure without using ‘’dialog.result’’.
Results¶
Once the dialog has been dismissed, dialog.result can be queried to see which button was pressed. For a file dialog, the return value will be one or more paths to the selected file(s), while for the other dialogs it will be one of the result codes from the table above.
1 | dialog.result ?
|
Examples¶
Yes/No Dialog Perl Script Example¶
This simple Perl script demonstrates opening a yesNo dialog and testing which button was pressed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #! perl
# Setup the dialog
lx( "dialog.setup yesNo" );
lx( "dialog.title "Confirm Operation"" );
lx( "dialog.msg "Perform the operation?"" );
lx( "dialog.result ok" );
# Open the dialog and see what button was pressed 10)
lx( "dialog.open" );
my $result = lxq( "dialog.result ?" );
if( $result eq "no" ) {
# User hit cancel
}
|
Yes/No Dialog Python Script Example¶
This is simple Python example opens a similar yesNo dialog. It uses an exception handler to handle the “no” case that is thrown when the user cancels the dialog. If no exception was thrown, we can assume the user clicked “Yes”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #python
# Written by Stuart Hall
import lx
try:
# set up the dialog
lx.eval('dialog.setup yesNo')
lx.eval('dialog.title {Confirm Operation}')
lx.eval('dialog.msg {Perform the operation?}')
lx.eval('dialog.result ok')
# Open the dialog and see which button was pressed
lx.eval('dialog.open')
lx.eval("dialog.result ?")
lx.out("Yes")
except:
lx.out("No")
|
Yes/No/Cancel Dialog Python Script Example¶
This simple Python example opens a yesNoCancel dialog and retrieves the result. It uses an exception handler to handle the “no” and “cancel” cases that are thrown when the user cancels or presses no, and queries for the result directly to differentiate between no and cancel.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #python
# Written by Chris Hague
import lx
# set up the dialog
lx.eval('dialog.setup yesNoCancel')
lx.eval('dialog.title {Really?}')
lx.eval('dialog.msg {Are You Sure?}')
# Open the dialog and see which button was pressed
try:
lx.eval('dialog.open')
userResponse = lx.eval("dialog.result ?")
except:
userResponse = lx.eval("dialog.result ?")
lx.out("Thank you for pressing %s." % userResponse)
|
File Dialogs¶
Creating a file or directory dialog is very similar to creating an information dialog. The fileOpen type opens a dialog asking for a single file, while fileOpenMulti allows for multiple selection within the file dialog. The fileSave type is similar to ‘’fileOpen’’, but warns if the selected file already exists. The dir type opens a dialog for selecting a directory.
In all cases, the dialog.result command can be used to set the initial path for the dialog. After the dialog is dismissed, dialog.result can be queried for the chosen path. In the case of ‘’fileOpenMulti’’, this will return an array of paths.
Open File Dialogs¶
The basic setup for a file dialog is just like that of an information dialog.
1 2 | dialog.setup fileOpen
dialog.title "Select a file to open"
|
Setting the Filetype¶
Open dialogs support filtering the load dialog by file type. A ‘’’file type’’’ is the class of data to be loaded or saved, such as an image or a scene. Save dialogs use the file type to provide a list of accepted file formats, plus the default file format displayed in the dialog. A ‘’’file format’’’ is a specific format within that file type, such as a Targa or JPEG image, or an LXO or LWO object.
The file type is set with ‘’’dialog.fileType’’’, where the argument is one of the known file types, such as ‘’text’’, ‘’script’’, ‘’config’’, ‘’macro’’, ‘’image’’, and so on. Alternatively, the name of any specific loader plug-in can also be used, such as ‘’$LWO’’. A list of loaders can be obtained with the HostService (ScriptQuery) interface. Furthermore, there is a special $temp file type, which can be filled in with ‘’dialog.fileTypeCustom’’. If no filetype is set, all files will be shown.
1 | dialog.fileType text
|
The file type of a specific loader can be found by querying its loader.classList tag from the hostservice ‘’ScriptQuery’’ interface. You must first ScriptQuery Overview#Selectors the loader before you can query it with ‘’server.infoTag’’. This example queries the LWO2 loader for its class.
1 2 | query hostservice server.name ? loader/$LWO2
query hostservice server.infoTag ? loader.classList
|
Note that this returns a space-delimited list of classes. Only one class should be passed to dialog.fileType, so you’ll need to extract the first one. In Perl, this can be done using ‘’split()’’.
1 2 3 4 5 6 7 8 9 10 11 12 | # "Select" the loader we want to query the tags of
lxq( "query hostservice server.name ? loader/$LWO2" );
# Query the loader.classList tag
my $classList = lxq( "query hostservice server.infoTag ? loader.classList" );
# Split the list at spaces
my @classes = split(' ', $classList);
# Setup the dialog with the first file type in the list 11) lx( "dialog.setup fileOpen" );
lx( "dialog.fileType @classes[0]" );
lx( "dialog.open" );
|
Default Paths¶
When the user chooses a file, the new location is stored in the config so that the next time the dialog is opened the file requester will point to that location. By default, all file dialogs point to the same place for a given file type, but it is often useful to be able to start at different locations depending on how the file will be used. For example, you generally don’t store your texture images with your final render images.
You can tell modo to separately remember a separate default file dialog path for your script for a particular file type by appending an @ and a name to the end of the file type passed to ‘’dialog.fileType’’. The tag can be any internal (ie: alphabetical characters only) string you like, and you may reuse tags defined by other systems. For example, the image file type could default to directories that the user previously navigated to for clips (textures) or renders by specifying item@clip or item@render as the file type.
The following example uses the text file type, storing and pulling the default path from the ForMyScript tag in the configs.
1 | dialog.fileType text@ForMyScript
|
Default Filename¶
The path the user has chosen is returned by ‘’dialog.result’’, but this can also be used to set a default open or save path (full path with filename), or just a default filename relative to the current path.
1 2 3 | dialog.result "MyFile.txt"
dialog.result "c:MyPathMyFile.txt"
dialog.result "c:MyPath"
|
If you pass in just the filename, as in the first example, then the file requester will start in the directory last used for that file type, as described above. If a fully qualified path is used, then any previously stored paths are ignored. This can become important when want to create an “export” or “save as” dialog where the user may commonly want to write to an alternate directory than the one the file originally existed in.
Displaying a File Dialog and Obtaining the Result¶
File dialogs are opened in the same manner as other dialogs, through the dialog.open command. The chosen path is read out by querying ‘’dialog.result’’. The latter will fail if the user canceled the dialog. For more information on handling command execution failures, see the specific Scripting Languages for how to handle command failure.
1 2 | dialog.open
dialog.result ?
|
Multi-Select File Dialog Perl Script Example¶
This Perl script demonstrates the use of a multi-select file dialog.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #! perl
# Setup the dialog
lx( "dialog.setup fileOpenMulti" );
lx( "dialog.title "Select Text Files"" );
lx( "dialog.fileType text@ForMyScript" );
lx( "dialog.result "c:\InitialPath"" );
# Open the dialog and get the list of files the user selected
if( !lx( "dialog.open" ) ) {
# User canceled the dialog
}
my @files = lxq( "dialog.result ?" );
foreach my $f (@files) {
# Process each filename
}
|
Save Dialog¶
A save dialog is identical to an open dialog, but adds dialog.fileSaveFormat to select a specific default file format within the file type set by ‘’dialog.fileType’’. This format will be selected by default when the dialog opens, and the one chosen by the user can be read by querying ‘’dialog.fileSaveFormat’’.
The file format can be set either by its default extension, which is the default behavior, or by the file format’s internal name. The list of available formats can be found using the hostservice ‘’ScriptQuery’’ interface. Which method is used is determined by the command’s ‘’second argument’’. Either way, both the extension and format can be read out by querying ‘’dialog.fileSaveFormat’’.
In this example, a save dialog is set up to use the image file type, and a default path is chosen.
1 2 3 | dialog.setup fileSave
dailog.result "c:InitialPath"
dialog.fileType image@ForMyScript
|
A list of file types for a particular format can be obtained by querying the hostservice ‘’server.infoTag’’ attribute with the saver.outClass selector, similar to how loader file types are queried.
1 2 | query hostservice server.name ? saver/$Targa
query hostservice server.infoTag ? saver.outClass
|
The Targa image file format is then chosen as the default save format. This can be done either by file extension:
1 | dialog.fileSaveFormat tga extension
|
Or it can be done by the format’s name:
1 | dialog.fileSaveFormat $Targa format
|
Next the file dialog is opened. This will fail if the user hit canceled, at which point a script could abort the operation.
1 | dialog.open
|
Finally, the path the user entered and the format and extension the user chose are ead.
1 2 3 | dialog.result ?
dialog.fileSaveFormat ? format
dialog.fileSaveFormat ? extension
|
Custom File Types¶
It is also possible to define a custom file type through ‘’’$temp’’’, which can represent any file formats you like through the dialog.fileTypeCustom command. Initially, this file type contains no formats, and is reset by ‘’dialog.setup’’. You can call dialog.fileTypeCustom multiple times to add any number of formats to the type. The first format added is automatically selected as the default file format.
‘’dialog.fileTypeCustom’’ takes four arguments. The first is a name for the format, such as targa or ‘’lwo’’. This is an arbitrary internal name for use by the script, and can be read out after the dialog is dismissed by querying ‘’dialog.fileSaveFormat’’. The second argument is the username for the format, which will be displayed in the dialog and may contain spaces, mixed case, and so on.
The final two arguments are the ‘’load pattern’’ and the ‘’save extension’’. The pattern is a semicolon-delimited list of file extensions that the particular file format supports. These are used to filter the load dialog. Each extension must include a leading asterisk and period for the filtering to work properly, such as ‘’.jpg;.jpeg’’.
The save extension is a single extension that will automatically be appended to the end of the filename selected in a save dialog. The period should not be entered, just the extension like ‘’lwo’’, tga or ‘’txt’’. You only need to specify the load pattern or save format as appropriate to the kind of dialog you’re opening.
Here is a simple Perl script example that lets the user decide if it should save some information as an XML file or an ASCII text file. The script adds two file formats, xml and ‘’text’’, as a custom file type, and after the dialog closes it retrieves the file name, format and extension of the format the user chose.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #! perl
# Setup the save dialog
lx( "dialog.setup fileSave" );
lx( "dialog.title "Save Data"" );
lx( "dialog.result "c:\InitialPath"" );
# Add two file formats, xml and text
lx( "dialog.fileTypeCustom xml "XML" "*.xml" xml" );
lx( "dialog.fileTypeCustom text "ASCII Text" "*.txt;*.text" txt" );
# Open the dialog
if( !lx( "dialog.open" ) ) {
# User canceled the dialog; abort
}
# Get the filename from the dialog
my $filename = lxq( "dialog.result ?" );
# Get the file format, which will be xml or text
# (the first argument passed to dialog.fileTypeCustom)
my $format = lxq( "dialog.fileSaveFormat ? format" );
# Get the format's extension, which will be xml or txt
# (the last argument passed to dialog.fileTypeCustom)
my $ext = lxq( "dialog.fileSaveFormat ? extension" );
|
Custom File Type Dialog wrapper function in Python¶
A convenient Python wrapper function that can be used for both saving and loading custom file types:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def customfile(type, title, format, uname, ext, save_ext=None, path=None):
''' Custom file dialog wrapper function
type : Type of dialog, string value, options are 'fileOpen' or 'fileSave'
title : Dialog title, string value.
format: file format, tuple of string values
uname : internal name
ext : tuple of file extension filter strings
save_ext: output file extension for fileSave dialog
path : optional default loacation to open dialog
'''
lx.eval("dialog.setup %s" % type)
lx.eval("dialog.title {%s}" % (title))
lx.eval("dialog.fileTypeCustom {%s} {%s} {%s} {%s}" % (format, uname, ext, save_ext))
if type == 'fileSave' and save_ext != None:
lx.eval("dialog.fileSaveFormat %s extension" % save_ext)
if path != None:
lx.eval('dialog.result {%s}' % path)
try:
lx.eval("dialog.open")
return lx.eval("dialog.result ?")
except:
return None
|
Example usage:
1 | swfile = customfile('fileOpen', 'Open Solidworks file', ('SWO',), 'Solidworks file', ('*.SLDASM;*.SLDPRT',),'SLDASM')
|
More Information¶
HostService (ScriptQuery)
User Interface