Session 12
Flexible Input Forms

Buttons in Pause Windows

Let's have a look at our pause window as it appears so far:

At the bottom, there are 3 buttons: Revert, Stop, and Continue. If the Revert button is clicked all fields are reverted to their default values. If default values are defined dynamically with the help of variables this button has no effect. Clicking the Stop button aborts the script instantly and an error message is shown.

Action buttons

The Continue button is defined in the last line of our pause window definition, after endPause: (the default option in line 3 is reversed to a literal value so that you can copy, paste, and test the pause window without the file handling stuff).

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." optionMenu: "Target Directory", 1 option: "good" option: "decent" option: "poor" endPause: "Continue", 1

The button definition consists of a string argument, denominating the button caption, and a numeric argument, specifying the pre-selected button (that's the button that can be 'clicked' by pressing Return on the keyboard). Concerning our example script above, one may prefer Save & Continue as a more appropriate caption—no problem:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." optionMenu: "Target Directory", 1 option: "good" option: "decent" option: "poor" endPause: "Save & Continue", 1

And if you want to prevent the user from accidentally saving the file to a wrong directory by thoughtlessly pressing Return, you can switch off pre-selection with an argument of 0:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." optionMenu: "Target Directory", 1 option: "good" option: "decent" option: "poor" endPause: "Save & Continue", 0

The pause window with the new button caption and without pre-selection:

Multiple buttons

The numeric default button argument is not a boolean argument (pre-selection on/off), but, as I wrote before, an argument specifying the pre-selected button. So far, we've only defined one button (Save & Continue), so the only meaningful specification is 1 (or 0 if you don't want pre-selection). But with pause windows, we're allowed to define more than one button! And then we can pick any one of them as default button with the final numeric argument.

To define additional buttons just add more button captions, separated by commas:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." optionMenu: "Target Directory", 1 option: "good" option: "decent" option: "poor" endPause: "Save & Continue", "Second button", "Third button", 1

Now, we have two more buttons, sharing the limited space at the bottom of the dialog window. Long captions are truncated:

Since we specified 1 as numeric argument, the first button (Revert and Stop do not count) is pre-selected. To make the third button the default, just specify it:

endPause: "Save & Continue", "Second button", "Third button", 3

Evaluating multiple buttons

We have three buttons now, but other than that we gained nothing much. Whether the user clicks the first, the second, or the third button, it's all the same to the script. What we really want is our script to acknowledge the different buttons and react accordingly. Fortunately, endPause returns the index of the clicked button and we can implement a conditional to assess the user's choice and react to different clicks with alternative code blocks:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." optionMenu: "Target Directory", 1 option: "good" option: "decent" option: "poor" clicked = endPause: "Save & Continue", "Second button", "Third button", 1 if clicked = 1 writeInfo: "Save & Continue was clicked" elsif clicked = 2 writeInfo: "Second button was clicked" elsif clicked = 3 writeInfo: "Third button was clicked" endif

In line 7 the return value of endPause—i.e. the index of the clicked button—is assigned to the variable clicked. The subsequent conditional evaluates the value of clicked and executes different commands, dependent on the clicked button.

Now we know enough to implement a useful application of multiple buttons. Consider the sound evaluation script:

list = Create Strings as file list: "SoundFiles", "sounds/*.wav" n = Get number of strings target_Directory = 1 for i to n selectObject: list filename$ = Get string: i fileID = Read from file: "sounds/" + filename$ Play beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." optionMenu: "Target Directory", target_Directory option: "good" option: "decent" option: "poor" endPause: "Save & Continue", 1 selectObject: fileID Save as WAV file: target_Directory$ + "/" + filename$ removeObject: fileID endfor removeObject: list

If the user agrees with the default option, one click is enough (Save & Continue). If the user disagrees with the default option, three clicks are necessary: (1) Open the pop-up menu, (2) select an option, and (3) confirm with Save & Continue. With multiple buttons it would be possible to provide the user with a dialog window, where one click is enough in both cases. Instead of providing the options in a pop-up menu, we just provide them as buttons:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." clicked = endPause: "Good", "Decent", "Poor", 1 if clicked = 1 target_Directory$ = "good" elsif clicked = 2 target_Directory$ = "decent" elsif clicked = 3 target_Directory$ = "poor" endif

The result is a pause window like this, which requires only one click:

You may have noticed that the Revert button is gone. That is, because there are no fields defined anymore which could be reverted to standard values; the only remaining field is a comment, which can't be reverted.

If you want the script to remember the user's last decision like in the old script, replace the literal numeric argument of endPause (1) with the variable clicked, since clicked contains the index of the previously clicked button. The sound evaluation script with 3 answer buttons and dynamically specified pre-selection:

list = Create Strings as file list: "SoundFiles", "sounds/*.wav" n = Get number of strings clicked = 1 for i to n selectObject: list filename$ = Get string: i fileID = Read from file: "sounds/" + filename$ Play beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." clicked = endPause: "Good", "Decent", "Poor", clicked if clicked = 1 target_Directory$ = "good" elsif clicked = 2 target_Directory$ = "decent" elsif clicked = 3 target_Directory$ = "poor" endif selectObject: fileID Save as WAV file: target_Directory$ + "/" + filename$ removeObject: fileID endfor removeObject: list

Cancel button

The last button discussed in this section is the Stop button. As I said before, clicking the Stop button aborts the script instantly and an error message is shown, indicating the line number of the 'uncompleted' endPause statement. This behavior may irritate an unexperienced user. To avoid this, you can get rid of the Stop button and alternatively implement a button—let's call it the Cancel button—that doesn't harass the user with an error message and even makes it possible for you to react to the Cancel click in the script before the exit. What we aim at, in short, is a more gracious Stop button.

We'll start with the name of the new button. Just insert a new button caption in the list:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." clicked = endPause: "Cancel", "Good", "Decent", "Poor", 2

The caption of the new button is arbitrary—Cancel, Quit, Halt, Suspend or everything else is just fine. In the example, the default button index is 2, so Good is pre-selected. But so far, Cancel is just a new button without function and the Stop button is still there.

To get rid of the Stop button a second numeric argument is required, specifying the index of the button with the 'cancel semantics'. Cancel seamtics is a fall-back strategy: If the user, instead of clicking a regular button, just closes the dialog window using a mechanism provided by the operating system, cancel semantics tells the script which button click to assume, thus preventing the script from vegetating in an undefined state. Consider the following button definition:

beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." clicked = endPause: "Cancel", "Good", "Decent", "Poor", 2, 1

Four buttons are defined, Cancel, Good, Decent, and Poor. The first numeric argument (2) declares that the second button (Good) is the pre-selected default button. The second numeric arguments (1) specifies that the first button (Cancel) adopts cancel semantics. So, if the user closes the window instead of clicking a button the script assumes that the Cancel button was clicked and proceeds with that assumption. A second effect of the existence of a second numeric argument is the disappearance of the Stop button:

In the last upgrade of the sound evaluation script, we implement the new pause window, adapt the preset of the default button in line 3, and extend the if-statement to be able to react to Cancel clicks or cancel semantics.

list = Create Strings as file list: "SoundFiles", "sounds/*.wav" n = Get number of strings clicked = 2 for i to n selectObject: list filename$ = Get string: i fileID = Read from file: "sounds/" + filename$ Play beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." clicked = endPause: "Cancel", "Good", "Decent", "Poor", clicked, 1 if clicked = 1 # react to cancel removeObject: fileID, list exitScript: "The script was aborted." elsif clicked = 2 target_Directory$ = "good" elsif clicked = 3 target_Directory$ = "decent" elsif clicked = 4 target_Directory$ = "poor" endif selectObject: fileID Save as WAV file: target_Directory$ + "/" + filename$ removeObject: fileID endfor removeObject: list

If the user closed the dialog window or clicked the Cancel button (if clicked = 1), we tidy up the object list and then exit the script with a message. The pop-up window that presents the message to the user resembles an error message. To avoid this you may use exitScript () instead, which exits silently.

list = Create Strings as file list: "SoundFiles", "sounds/*.wav" n = Get number of strings clicked = 2 for i to n selectObject: list filename$ = Get string: i fileID = Read from file: "sounds/" + filename$ Play beginPause: "Set the target directory" comment: "Choose the appropriate directory for this sound." clicked = endPause: "Cancel", "Good", "Decent", "Poor", clicked, 1 if clicked = 1 removeObject: fileID, list # silent exit exitScript () elsif clicked = 2 target_Directory$ = "good" elsif clicked = 3 target_Directory$ = "decent" elsif clicked = 4 target_Directory$ = "poor" endif selectObject: fileID Save as WAV file: target_Directory$ + "/" + filename$ removeObject: fileID endfor removeObject: list
Next: Workshop: Flexible Input Forms