BUTTON, BUTTON…

So many automation projects you work with may require a button. Multi-state objects are one instance. This is especially true when the multi-state object is included as part of a Publish Online project. In this post we will look at a number of ways a button can be added to the multi-state project we created in the previous blog post. For our purpose we will use a cut down version of the handler used there just for demonstration. For our multi-state object, using a simple rectangle just will not do the job. We need to have buttons that indicate going to the next or the previous slide. The addButton handlers presented below expect a document to be open having RGB Cyan and Black as part of its color swatch list. Notice that the handlers create the button but do not associate them with the multi-state object.

set gBounds1 to {100, 400, 130, 430}--geometric bounds
set gBounds2 to {100, 470, 130 500}
set btn1 to addButton {gBounds1}
set btn2 to addButton {gBounds2}
--the addButtons handler
on addButton(gBounds)
tell application "Adobe InDesign CC 2018"
set docRef to document 1
set fColor to swatch "RGB Cyan" of docRef--fill color
set sWid to 1 --stroke width
set fTint to 100  --fill tint
set sColor to swatch "Black" of docRef --stroke color
set btnProps to {fill color:fColor, fillTint:fTint, stroke weight:sWid, stroke color:sColor}
tell page 1 of docRef
set btn1 to make button with properties {geometric bounds:btn1Bounds} & btnProps
end tell
set btn2 to make button with properties {geometric bounds:btn2Bounds} & btnProps
end tell
end tell
return {btn1, btn2}
end addButtons

The buttons created with this handler will be simple rectangles. Based on this basic code structure, the following handlers will demonstrate some options that can be used for creating triangular (arrow) buttoms.

RECTANGLE CONVERTED TO TRIANGLE

One of the simplest solutions to the problem is to to convert the rectangular buttons to triangles. We will do that with the handler below. Notice that three parameters are passed to the handler: the object’s name, geometric bounds and, because by default the triangle would point up, the value for a counterclockwise rotation is also passed. (In a real world solution you most likely would also pass values for the fill color, stroke color, stroke width, and fill tint.

set gBounds1 to {500, 350, 518, 370}
set gBounds2 to {500, 400, 518, 420}
set btn1 to addButton("LefButton", gBounds1, 90)
set btn2 to addButton("RightButton, gBounds2, -90)
--the addButtons handler
on addButton(btnName, btnBounds, theAngle)
tell application "Adobe InDesign CC 2018"
set transMatrix to make transformation matrix with properties {counterclockwise rotation angle:theAngle}
set docRef to document 1
set fColor to swatch "RGB Cyan" of docRef
set sWid to 1 --stroke width
set fTint to 100 --fill tint
set sColor to swatch "Black" of docRef --stroke color
set btnProps to {fill color:fColor, fillTint:fTint, stroke weight:sWid, stroke color:sColor}
tell page 1 of docRef
set theBtn to make button with properties {name:btnName, geometric bounds:btnBounds} & btnProps
--statements removed that connect the button to the multi-state object
tell theBtn to convert shape given convert to polygon number of sides 3 inset percentage 0
transform theBtn in page coordinates from center anchor with matrix transMatrix
end tell
end tell
return theBtn
end addButton

MAKE POLYGON

More direct to the point you could have a handler that creates the triangular buttons using the entire path property for a polygon. The entire path property for a straight-sided page item (no curves) is a list of its path points (the x-point is listed before the y-point coordinate). The code below demonstrates using the button’s first state (state 1) to create the polygon. The advantage of creating the button this way is that you can add states and change the appearance of the button for on click, and on rollover. To keep our final script simple, we will not use states.

set path1 to {{370, 506}, {355, 512}, {370, 518}}
set path2 to {{400, 506}, {415, 512}, {400, 518}}
set gBounds1 to {506, 350, 524, 375}
set gBounds2 to {506, 400, 524, 425}
set btn1 to addButton("LeftButton", gBounds1, path1)
set btn2 to addButton("RightButton", gBounds2, path2)
--the addButtons handler
on addButton(btnName, btnBounds, pathPoints)
tell application "Adobe InDesign CC 2018"
   set docRef to document 1
   set fColor to swatch "RGB Cyan" of docRef--fill color
   set sWid to 1 --stroke width
   set fTint to 100 --fill tint
   set sColor to swatch "Black" of docRef --stroke color
   set btnProps to {fill color:fColor, fillTint:fTint, stroke weight:sWid, stroke color:sColor}
   tell page 1 of docRef
      set theBtn to make button with properties {name:btnName, geometric bounds:btnBounds}
      tell state 1 of theBtn
         set myArrow to make polygon with properties btnProps
         set entire path of path 1 of myArrow to pathPoints
      end tell
   end tell
end tell
return theBtn
end addButton

BUTTON FROM LIBRARY

If you have not worked with the button library provided with InDesign, here is your chance to do so. The code for the handler below takes a detour from the code used above as it needs to make sure the library is open. Placing an asset from the Button Library, poses a problem in that the button is first placed into the document, then moved to the page and, finally, to the desired position on the page.

set btnNum1 to 143
set btnNum2 to 144
set placePt1 to {350, 510}
set placePt2 to {400, 510}
set btn1 to addButton("LeftButton", placePt1, btnNum1)
set btn2 to addButton("RightButton", placePt2, btnNum2)
--the handler
on addButton(btnName, placePt, btnNumber)
tell application "Adobe InDesign CC 2018"
   set docRef to document 1
   set pageRef to page 1 of docRef
   if not (exists library "ButtonLibrary.indl") then
	set appPath to file path as string
	set libPath to appPath & "Presets:Button Library:ButtonLibrary.indl"
	set libRef to open libPath
   else
	set libRef to library "ButtonLibrary.indl"
   end if
   set assetRef to asset ("" & btnNumber) of libRef
   set placedObj to place asset assetRef on docRef
   move placedObj to pageRef
   move placedObj to placePt
   set theBtn to item 1 of placedObj
   return theBtn
end tell
end addButton

…Buttons created with first three handlers

BUTTONS WITH STROKE ONLY

Should you want to place those sexy line only buttons over an image or colored object, the following provides a fourth option. This version takes advantage of using the button’s state.

set path1 to {{370, 430}, {355, 450}, {370, 470}}
set path2 to {{400, 430}, {415, 450}, {400, 470}}
set gBounds1 to {430, 350, 470, 375}
set gBounds2 to {430, 400, 470, 425}
set btn1 to addButton("LeftButton", gBounds1, path1, false)
set btn2 to addButton("RightButton", gBounds2, path2, false)
--the addButtons handler
on addButton(btnName, btnBounds, pathPoints, closePath)
tell application "Adobe InDesign CC 2018"
  if closePath is true then
      set myPathType to closed path
  else
      set myPathType to open path
  end if
  set docRef to document 1
  tell docRef
     if not (exists layer "Button Layer") then
       set layerRef to make layer with properties {name:"Button Layer"}
     else
       set layerRef to layer "Button Layer"
     end if
     set fColor to swatch "Paper"--fill color
     set fTint to 0--fill tint
     set sWid to 3 --stroke width
     set sColor to "Paper" --stroke color
     set btnProps to {stroke weight:sWid}
     tell page 1
       set theBtn to make button with properties {name:btnName, item layer:layerRef, geometric bounds:btnBounds, fill color:"None"}
       tell state 1 of theBtn
         set myArrow to make polygon with properties btnProps
         set fill color of myArrow to "None"
         set entire path of path 1 of myArrow to pathPoints
         set stroke color of myArrow to sColor
         set path type of path 1 of myArrow to myPathType
       end tell
     end tell
  end tell
end tell
return theBtn
end addButton

…Line only buttons

TEST BEHAVIORS

To associate the buttons to a multi-state object, we add behaviors. To test the buttons the Call Handler code below adds go to previous and go to next behaviors. To test the buttons created in the handlers above, run the script from our previous blog to create the multi-state object. Make sure the document created includes the RGB Cyan swatch. Remove the test buttons and save. Substitute the values from the top of the demonstration scripts above into the following and make changes as necessary. Add one of the addButton handlers below to test.

CALL HANDLER

This top portion calls the addButton handler for the Make Polygon example above

set path1 to {{370, 506}, {355, 512}, {370, 518}}
set path2 to {{400, 506}, {415, 512}, {400, 518}}
set gBounds1 to {506, 350, 524, 375}
set gBounds2 to {506, 400, 524, 425}
tell application "Adobe InDesign CC 2018"
  set docRef to document 1
  set MSObject to multi state object "Slideshow" of document 1
  set btn1 to my addButton("LeftButton", gBounds1, path1)
  set btn2 to my addButton("RightButton", gBounds2, path2)
  tell page 1 of docRef
     tell btn1
        make goto previous state behavior with properties {associated multi state object:MSObject, behavior event:mouse down, enable behavior:true, loops to next or previous:true}
     end tell
     tell btn2
        make goto next state behavior with properties {associated multi state object:MSObject, behavior event:mouse down, enable behavior:true, loops to next or previous:true}
     end tell
  end tell
end tell

Changes needed for the other examples:

  • Notice that the calls to the handlers now include the word my as the call is being made from within a tell statement to the InDesign application.
  • The call to the handler for Buttons with Stroke includes a fourth parameter: false to indicate that the path will not be closed.
  • The call to the handler for the Library Buttons example uses place point instead of bounds. It also passes a value for the number of the button in the library.

ONWARD AND UPWARD

What other method could you think of for creating a button programmatically? Using the code structure above do some experimenting. Our next blog will add user interface to round out the Slideshow script.

Disclaimer

Scripts presented are for the purpose of demonstration and are not represented to be complete or error-free. Users are advised to use the code at their own discretion.