WORKING WITH PREFERENCES

When writing a script that sets InDesign application preferences it is always a good idea to capture the existing setting before changing. When the process that depends on the preference setting is completed, the script needs to return the value back to its original.

Lets look at a few examples.

User Interaction Level

Setting and resetting the script preference user interaction level is a common practice you may find in scripts that create a user dialog. In order for a user dialog window to show, the script preference user interaction level needs to be set to interact with all.

AppleScript

--call to dialog handler
try
   set dlgResult to userDialog()
on error errStr
   activate
   display alert "Error: " & errStr
end try
(*dialog handler sets and resets user interaction level; 
returns result or error*)
on userDialog()
   set dialogName to "Name Here"
   tell application "Adobe InDesign CC 2017"
	set origLevel to user interaction level of script preferences
	set user interaction level of script preferences to interact with all
	set dlgRef to make dialog with properties ¬
{name:dialogName, can cancel:true, label:dialogName}
	tell dlgRef
	   tell (make dialog column)
		--add dialog widgets here
	   end tell --column
	end tell --dialog
	set userResponse to show dlgRef
	if userResponse = true then
	   --put results from widgets into list
	   set resultList to {}
	end if
	destroy dlgRef
	--reset preference back to original level
	set user interaction level of script preferences to origLevel
	--return captured values back to main part of script
	--handle error if user clicks Cancel button
	if (userResponse is false) then
	   error ("User Cancelled")
	end if
   end tell
   --the script does not get here if user cancelled
   return resultList
end userDialog

ExtendScript

try {
   var dlgResult = userDialog ();
   dlgResult;
} catch  (errMsg) {
    alert  ("Error: "+ errMsg);
}
function userDialog() {
   var dialogName = "Name Here"
   var origLevel= app.scriptPreferences.userInteractionLevel;
   app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;
   var dlgRef = app.dialogs.add({name:dialogName, canCancel:true, label:dialogName}) ;
   with(dlgRef){
	with(dialogColumns.add()){
	   //add dialog widgets here
	}
   }
   userResponse = dlgRef.show();
   if (userResponse == true){
	//Place results iin array
        var resultArr = new Array;
   }
   //Remove the dialog window from memory.
   dlgRef.destroy();
   app.scriptPreferences.userInteractionLevel = origLevel;
   if(userResponse == false) {
	throw ("User Cancelled");
   }
   //script doesn't get here if user cancels
   return resultArr;
}

Notice in the above examples that the dialog window is destroyed and the user interaction level of script preferences is reset irrespective of whether the user clicks OK or Cancel.

Measurement Units

AppleScript

tell application "Adobe InDesign CC 2017"
   set origUnit to measurement unit of script preferences
   set measurement unit of script preferences to points
   --code that uses points for measurements
   set measurement unit of script preferences to origUnit
end tell

ExtendScript

var origUnit = app.scriptPreferences.measurementUnit;
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
//code that uses points for measurements
app.scriptPreferences.measurementUnit = origUnit; 

Another common practice is to set and reset the horizontal and vertical measurement units for view preferences.

AppleScript

--assumes document 1 exists
tell application "Adobe InDesign CC 2017"
	set origH to horizontal measurement units of view preferences
	set origV to vertical measurement units of view preferences
	set horizontal measurement units of view preferences to points
	set vertical measurement units of view preferences to points
	tell page 1 of document 1
		set rectRef to make rectangle with properties ¬
{geometric bounds:{100, 50, 36, 150}, fill color:"Black", fill tint:50, stroke weight:0}
	end tell
	set horizontal measurement units of view preferences to origH
	set vertical measurement units of view preferences to origV
end tell

ExtendScript

var origH = app.viewPreferences.horizontalMeasurementUnits;
var origV = app.viewPreferences.verticalMeasurementUnits;
app.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.POINTS;
app.viewPreferences.verticalMeasurementUnits = MeasurementUnits.POINTS;
var pageRef = app.documents[0].pages[0];
var rectRef= pageRef.rectangles.add({geometricBounds:
[100, 50, 36, 150], fillColor:"Black", fillTint:50, strokeWeight:0});
app.viewPreferences.horizontalMeasurementUnits = origH;
app.viewPreferences.verticalMeasurementUnits = origV;

The advantage of this second method is that it allows the horizontal and vertical units to be set to different values.

Note:The measurement unit for script preferences overrides that for the view preferences. If you have a script that uses view preferences to set the measurement unit and the script preferences is set to a different unit you may have unexpected results or an error that reads Data is out of range. Make sure that the measurement unit for script preferences is set to auto value.

PUTTING CONCEPTS TO WORK

We can use code from the above examples as part of code that you might want to have handy as the start for a script that creates and names multiple page items consecutively.

AppleScript

set baseName to "Text"
set numberItems to 4
set topBound to 30
set leftBound to 30
set boxWidth to 120
set boxHeight to 50
set spaceBetween to 20
--assumes document 1 exists with paragraph style "Title"
tell application "Adobe InDesign CC 2017"
   set docRef to document 1
   set fColor to swatch "Black" of docRef
   set pStyle to paragraph style "Title" of docRef
   set pageRef to page 1 of docRef
   set origUnit to measurement unit of script preferences
   set measurement unit of script preferences to points
   --arguments: parent reference, layer name, at top boolean
   set boxLayer to my makeLayer(docRef, "boxLayer", false)
   set rightBound to leftBound + boxWidth
   repeat with i from 1 to numberItems
	set thisName to (baseName & i)
	set gBounds to {topBound, leftBound, topBound + boxHeight, rightBound}
	(*arguments: parent reference, name, geometric bounds, fill color, 
fill tint, stroke weight, stroke color, stroke tint, layer reference)*)
	set rectRef to my makeRectangle¬
(pageRef, thisName, gBounds, fColor, 50, 0, "None", 100, boxLayer)
	set textLabel to ("Text " & i)
	set textRef to my makeTitlebox¬
(pageRef, thisName, gBounds, pStyle, textLabel, boxLayer)
	set topBound to topBound + boxHeight + spaceBetween
   end repeat
end tell

(*creates a text frame with title as defined by textLabel value passed
Text frame has no fill or stroke*)
on makeTitlebox(parentRef, itemName, gBounds, pStyle, textLabel, layerRef)
   tell application "Adobe InDesign CC 2017"
	tell parentRef
	   set titleRef to make text frame with properties ¬
{name:itemName, geometric bounds:gBounds, itemlayer:layerRef, fill color:"None", stroke weight:0, stroke color:"None", contents:textLabel}
	   set applied paragraph style of paragraph 1 of titleRef to pStyle
	   set vertical justification of text frame preferences of titleRef to center align
	end tell
   end tell
   return titleRef
end makeTitlebox
(*creates rectangle using values passed in argument list*)
on makeRectangle(parentRef, itemName, gBounds, fColor, fTint, sWeight, sColor, sTint, layerRef)
   tell application "Adobe InDesign CC 2017"
	tell parentRef
	   set rectRef to make rectangle with properties {name:itemName, ¬
geometric bounds:gBounds, fill color:fColor, fill tint:fTint, stroke weight:sWeight, stroke color:sColor, stroke tint:sTint, item layer:layerRef}	
	end tell
   end tell
   return rectRef
end makeRectangle
(*Creates layer if one named layerName does not exist; returns reference to layer*)
on makeLayer(parentRef, layerName, atTop)
   tell application "Adobe InDesign CC 2017"
	tell parentRef
	   if not (exists (layer layerName)) then
		if atTop then
		   set layerRef to make layer with properties ¬
{name:layerName, locked:false, visible:true}
		else
		   set layerRef to make layer with properties {name:layerName}
		   move layerRef to after layer -1
		end if
	   else
		if locked of layer layerName is true then
		   set locked of layer layerName to false
		end if
		set layerRef to layer layerName
	   end if
	end tell
   end tell
   return layerRef
end makeLayer 

This script introduces a number of handlers (functions) that you might want to add to your handler library (see previous blog post).

..Page items created by the script

ON YOUR OWN

In the script above, notice the number of variables that have values hard coded at the top of the script. To make it user friendly you will want to add a custom dialog to have the user supply values for box fill color, tint, stroke weight, stroke color, stroke tint, paragraph style, base name, topBound, leftBound, rightBound, boxHeight, spaceBetween, and number of items.

Disclaimer: Code samples are to be used as a guide for users to create their own real world scripts and is provided “AS IS”. No representation is made as to the accuracy or completeness of the code. Use of the code and its operation is at the discretion and responsibility of the user.