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.

MAKE DIALOG

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

  • InDesign must be frontmost (activate)
  • user interaction level for script preferences must allow user interaction
  • the dialog window is modal and must be opened and later closed (destroyed) after interaction is completed

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.

ADDING DIALOG WIDGETS

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

EDITBOXES

Text Editbox

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:

  • min width (the minimum width of the control expressed as points).
  • edit contents – The text value for the control. This can be set as a default value.

Real and Integer Editboxes

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.

Percent Editbox

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.