Designer ES2 Macros

Hey, it has been a while since I posted.  Lots of stuff on my plate.  Occasionally they make me do real work around here. 

Have you installed ES2 Designer yet?  If you have, then there is a new experimental feature that you can play with.  Macros.  I want to tell you all about them.  But first the caveats:

  1. ES2 Designer macros are an experimental (prototype) feature
  2. ES2 Designer macros are not officially supported
  3. Macros developed for Designer ES2 are not guaranteed to work in the next release of Designer.

We figured out the architecture for this feature fairly late in the ES2 development cycle.  We think macros have lots of potential, but we didn’t have the resources to finish the job in ES2.  So we’ve put it out there as a prototype.  You get to kick the tires.  Tell us if you like it.  Let us know what enhancements are needed.

Overview

Design Macros provide an external plugin interface to Designer, so that 3rd parties like partners or customers can extend the functionality of Designer. Some examples:

  • Rename a field or subform and update all the script references
  • Add metadata to form objects (<extras> or <desc>)
  • Find all scripts that consist entirely of comments
  • Add an onEnter script to all fields

Macro Script

The macro itself consists of a JavaScript file.  The JavaScript in the macro has full access to the template model. (I have a previous blog post that talks about scripting to the template: Template Transformation ).  The basics are that the scripting knowledge  from coding your form script transfers nicely to the Designer environment.

In addition to the template DOM, there’s an object in the root namespace called "designer" that has methods that you can use to communicate directly with the Designer application.

Flash Dialogs

One of the methods on the designer object allows you to launch a flash dialog (.SWF)and allows you to exchange strings with the dialog.  This allows you to build a custom UI.

Installing a Plugin

To install a plugin:

  1. Create a folder named "scripts" in the Designer install directory.
  2. In the scripts folder, create a folder for your plugin, i.e. "MyPlugin"
  3. In the scripts \ MyPlugin folder, create a JavaScript file (this is the actual plugin), i.e. "MyPlugin.js"
  4. Place any SWF files used by the plugin in the same directory.

When Designer starts up, it searches its install directory for a folder called scripts. If this folder is found, Designer will then search each child folder of scripts looking for *.js files.

Every *.js file found (and there can be more than one in the same folder) will appear as a menu entry under the Tools | Scripts menu. This menu entry on the Tools menu appears only if the \scripts directory exists and there is at least one *.js file in a subdirectory of the \scripts folder.

To run the plugin, select the plugin you want to run from the Tools | Scripts menu.

The Designer API

Here follows a description of the methods that are available on the designer object.

/**
* Output a message to the log window in Designer.
* (Note that the log window in designer will not emit any
* duplicate strings)
* @param sMsg The text to push to the log window
*/
void designer.println(sMsg)


/**
* returns the object (or objects) currently selected
* on the canvas or in the hierarchy dialog. If nothing is
* currently selected, the list returned will be empty.
* @return a nodelist
*/
nodelist designer.getSelection()

 

/*
* Create a new modal dialog window from a provided
SWF.
*
* @param sSWF The name of a *.swf file to load.
* Note that the *.swf file must be in
* the same directory that the plugin is installed in. 
* The sSWF parameter should only contain a file name,
* no path information.
*
* @param nWidth The width of the Flex dialog
* @param nHeight The height of the Flex dialog
*
* @return a string that comes from the
* Flex application.  When the Flex application terminates, it
* can pass back a string. Commonly used to send back it’s
* closing status, e.g. "OK" or "Cancel"
*/
string designer.showFlexDialog(sSWF, nWidth, nHeight)

/*
* This method writes out a text file (showTextWindow.txt) to
* the system’s temporary directory with the content of sText
* then launches the system’s default *.txt file editor with
* that file as a parameter.
*
* This method allows a non-modal way of showing output.
* The Flex dialog and the alert dialog are both modal – this
* makes it impossible for a user to interact with the output
* of a plugin at the same time they interact with Designer.
*
* @param sText The text to show in the system’s default
* text editor.
*/
void designer.showTextWindow(sText)

/**
* This function creates an XDP data file from the 
* supplied data and will launch a PDF file with that data.
* This allows rich reporting from a plugin script.
* Note that this function looks for an installed version of
* Acrobat, and will not work with Reader.

* @param dataPacketString The XML data to be written out
* @param pdfName The base name of the PDF file to display,
* which must be in the plugin directory.
*/
void designer.showXDPinAcrobat(dataPacketString, pdfName);

/**
* This function is used to get data out of the Flex dialog
* invoked by designer.showFlexDialog(). The Flex dialog can
* send data to Designer by calling:
* ExternalInterface.call("setDialogString",
*                          "VariableName", "VariableValue");
*
* If the Flex dialog makes this external call to Designer, then
* once the dialog is dismissed, "VariableName" is available for
* inspection in the plugin through a call to:
* designer.getDialogString();
* In this particular example, the call would be:
* designer.getDialogString("VariableName");
* The return value would be "VariableValue".
*
* @param sFieldName The name of the field to inspect.  
* This field is available for inspection only if the Flex
* application made the appropriate ExternalInterface call.
*
@r
eturn The value of sFieldName or empty if the Flex
* application did not set that value.
*/
string designer.getDialogString(string sFieldName);

/**
* This method is used to push data into the Flex dialog before
* calling designer.showFlexDialog(). If the plugin wants to set
* data inside the Flex dialog, it needs to call
* designer.setDialogString();
* with the data before invoking designer.showFlexDialog().
*
The Flex application, in turn, needs to call
*
ExternalInterface.call("getDialogString", "sFieldName")
*
* @param sFieldName The name of the variable to set
*
@param sValue The value of sFieldName.
*/
void designer.setDialogString(sFieldName, sValue)

/**
* Show a message box in Designer with sMsg as the text.
* @param sMsg The message to display in the message box.
*/
void designer.alert(sMsg);

An Example

Over time I hope to share a bunch of sample macros.  But to get started, here is a fairly simple macro that should wet your appetite.

The macro refactor.js will rename a field object.  In addition to renaming the field, it will find all occurrences of that field in scripts and will rename it there as well. It uses refactor.swf as a ui to modify the scripts.

Step 1.

Install the macro.  Place the .js and .swf files below the Designer install.  On my system this looked like:

refactorScreen2

Step 2.

Open a PDF in Designer ES2.  I used this file to test.

Step 3.

Select the field to rename

Step 4.

Launch the macro:

refactorScreen1

Step 5.

When the flash dialog pops up, enter a new name for the field. Then use the buttons to find/replace the field name in scripts

refactorScreen3

When the dialog is dismissed, the form will be updated with all the changes.

Here is the rest of the collateral you’ll need (right click to download):

 

Whew.  That’s a lot to absorb.  I hope to offer some more samples soon.