Your prescription for increased productivity and profitability
When it comes to interacting with the user, AppleScript gives you a number of choices. With Adobe InDesign, you have even more. In this post we will look at working with InDesign’s dialog object.
The code for creating a dialog in InDesign can be fairly involved depending on the number of widgets (dialog objects) required, but it is not difficult.
What adds to the mix are the InDesign requirements
With these three requirements in mind, a basic dialog can be created with the following:
tell application "Adobe InDesign CC 2019" activate set dlgRef to make dialog with properties {can cancel:true} --establish script preferences set origLevel to user interaction level of script preferences set user interaction level of script preferences to interact with all tell dlgRef --enter widget information here end tell --open the dialog set userResponse to show dlgRef if userResponse = true then --get user information here set theInfo to {} --add values or variables to a list end if --close the dialog destroy dlgRef --reset script preferences set user interaction level of script preferences to origLevel --if user cancelled, throw an error if userResponse = false then error "User Cancelled" else --pass information to next process return theInfo end if end tell
If you run the script at this point you will get a little window with an OK and Cancel button. If you set the value of can cancel to false, the window will only have an OK button.
Other properties you may want to set for the window are a name and a label:
set dlgRef to make dialog with properties {name:"User Info", can cancel:true, label:"userInfo"}
To organize your script and handle the result you may want to put the dialog procedure inside a handler called within an error trap. Trapping the Cancel is up to you as pressing the Cancel button destroys the dialog window when closed.
--call the dialog handler and capture its information to the userInfo variable try set userInfo to userDialog ("User Info", true, "userInfo") on error errStr activate display alert "Error: " & errStr end try --the handler on userDialog (dlgName canCancel, dlgLabel) tell application "Adobe InDesign CC 2019" activate set dlgRef to make dialog with properties {name: dlgName, can cancel:canCancel, label:dlgLabel} --the rest of the script is the same as above end userDialog
You may want to save the script at this point as a template for creating dialogs in the future. Notice that the dialog is closed (destroyed) and the script interaction level is reset before trapping the Cancel. Just be sure the window is closed and user interaction level is returned to its previous state.
Think of a dialog as a table with rows and columns. The dialog itself can contain columns and columns can contain rows. To add a widget to the dialog, you start with a column to which you add rows. Within rows you can add widgets such as labels (static text), and fields (such as editboxes and controls). More about these later.
When you create a dialog column or dialog row, you can place a reference to the parent object in a variable and then use the variable to create other objects:
tell dlgRef --enter widget information here set dlgCol to make dialog column tell dlgCol set dlgRow to make dialog row tell dlgRow make static text with properties {static label:"Enter your name: "} set nameField to make text editbox with properties {min width: 144} end tell end tell end tell
To save some lines of code and make the script more readable, you can combine a tell and a make statement. With this, the tell dlgRef block above can be written:
tell dlgRef --enter widget information here tell (make dialog column) tell (make dialog row) make static text with properties {static label:"Enter your name: "} set nameField to make text editbox with properties {min width:144} end tell end tell end tell
Notice here that the only variable created in this example is for the object that will contain the information provided by the user. Inside the if statement near the bottom, this can be written as follows:
if userResponse = true then set theName to edit contents of nameField set theInfo to {theName} end if
Here a variable is created to get the information. It is then passed back to the main part of the script as part of a list. The variable and list are used in anticipation of a number of widgets being added to the dialog. At this point the entire script can read as follows:
try set userInfo to userDialog("User Info", true, "userInfo") copy userInfo to {theName} activate display alert "Name entered " & theName on error errStr activate display alert "Error: " & errStr end try on userDialog(dlgName, canCancel, dlgLabel) tell application "Adobe InDesign CC 2019" activate set dlgRef to make dialog with properties {name:dlgName, can cancel:canCancel, label:dlgLabel} --establish script preferences set origLevel to user interaction level of script preferences set user interaction level of script preferences to interact with all tell dlgRef --enter widget information here tell (make dialog column) tell (make dialog row) make static text with properties {static label:"Enter your name: "} set nameField to make text editbox with properties {min width:144} end tell end tell end tell --open the dialog set userResponse to show dlgRef if userResponse = true then --get user information here set theName to edit contents of nameField set theInfo to {theName} end if --close the dialog destroy dlgRef --reset script preferences set user interaction level of script preferences to origLevel --if user cancelled, throw an error otherwise return theInfo if userResponse = false then error "User Cancelled" else --pass information to next process return theInfo end if end tell end userDialog
An example of creating a text editbox and getting its value is shown in the script above.
Properties that can be set for the text editbox are:
For number values the dialog object provides a real editbox and an integer editbox. These have a number of properties that can be set:
For the editbox entry, the edit contents or edit value property can be used (one or the other but not both). Edit contents returns a string value while edit value returns a real for both the real and integer editbox.
To determine the acceptable value range, the maximum value and minimum value properties are used.
Using arrow keys with or without the shift key, the user can increment or decrement the editbox value. The amount of change is set using the small nudge (without the shift key) and large nudge (with the shift key) properties.
With this an integer editbox can be added to the dialog using code that might read as follows. Place this inside the tell statement block that creates the dialog column.
tell (make dialog row) make static text with properties {static label:"Enter your age: "} set ageField to make integer editbox with properties {min width:72, minimum value:10, maximum value:100, small nudge:1, large nudge:10} end tell
To get the real number value from the integer editbox, place the following inside the if userResponse = true conditional:
set theNumber to edit value of ageField
This returns a real number value that can be coerced to an integer using:
set theInt to (edit value of ageField as integer)
If the user enters a decimal value, it is accepted but the integer value is rounded up by default. If the user enters a non-number value, an alert is posted and the script paused for the user to re-enter a valid number value. Behavior for the real editbox is similar.
The percent editbox has the same behavior as the real and integer editboxes with the exception that it adds a percent sign after the number entered when the field loses focus (user tabs or otherwise activates another field). Additionally, it will accept a percent sign as part of the entry which would cause either the real or integer widget to throw an error.
tell (make dialog row) make static text with properties {static label:"Enter score from test: "} set scoreField to make percent editbox with properties {min width:72, minimum value:10, maximum value:110, small nudge:1, large nudge:10} end tell
In getting the value of the percent editbox, if edit contents is used, the value returned is a string with the percent sign.
set thePcent to (edit contents of scoreField) --if user enters 100 the result will be "100%"
Otherwise the result will be a real number
set thePcent to (edit value of scoreField) --if user enters 100 the result will be 100.0
In our post for next week, we will look at other dialog widgets that you can add to your script as well as ways you can dress up the appearance of your dialog.