DollyXs command line tool

What is DollyXs?

Dolly is a Java application for generating new InDesign plug-in projects. It is included with the Plug-in SDK. Dolly has a simple user interface, but it can also be used from the command line. User interface version of Dolly has a limited amount of settings that you can adjust. Using command line tool opens up a bigger range of options via manipulating the XML document directly. You can create many different input files and use them as templates for your plug-in development. In this blog post, I’ll show you how to use the command line to generate new InDesign plug-in projects.

Running Dolly

First, we’ll launch Dolly from the command line. Dolly is located inside the plug-in SDK: /devtools/sdktools/dollyxs.
Screen Shot 2013-02-20 at 11.53.18
We’ll need to open command prompt or terminal and set the current directory to /devtools/sdktools/dollyxs. Let’s first try running Dolly with user interface option turned on.

Windows: DollyXs.bat win-input.xml
Mac: DollyXs.sh mac-input.xml

You should be able to see the UI for Dolly:
Screen Shot 2013-02-20 at 12.47.14
The input files win-input.xml and mac-input.xml are the default XML documents that Dolly uses to generate projects. They define the properties of your new plug-in, such as whether you’re creating a model or a UI plug-in or if it is for InDesign or InCopy. It is not necessary to provide these files explicitly when running Dolly with UI.
Now close Dolly and try launching it with user interface disabled. To do that we’ll use the -q flag.

Windows: DollyXs.bat -q win-input.xml
Mac: DollyXs.sh -q mac-input.xml

If we look at mac-project-dir or win-project-dir attributes in the XML document we’ll see the location where the project was created. If you haven’t used Dolly before, the chance is that you got an error ‘Failed to create output file… ‘ when trying to create a project. It is because your mac-project-dir or win-project-dir point to an invalid location, like:

mac-project-dir="/id8sdk/build/mac/prj"

In the next part, we’ll try and use our own XML input file to generate projects using Dolly command line tool.

Creating custom input file

Copy win-input.xml or mac-input.xml and rename it myInputFile.xml. This is going to be the file we’ll be working on.

We’ll now define some general information about our plugin. Open myInputFile.xml and change author field to your name. Edit the value of long-name and change it to “MyPlugin”.

author="Alex"
long-name="MyPlugin"

We’ll also update the location of our project to something more suitable. That should fix any errors that we might have encountered before. Change mac-project-dir to /build/mac/prj and win-project-dir to /build/win/prj.

mac-project-dir="/Users/Alex/Desktop/Adobe_InDesign_CS6_Plugin_SDK/build/mac/prj"
win-project-dir="/Users/Alex/Desktop/Adobe_InDesign_CS6_Plugin_SDK/build/win/prj"

Dolly is going to generate some .cpp and header files for us. Let’s put them all in the same place so they are easily accessible. We can do this by assigning the same path to mac-id-header-dir, mac-source-dir, win-id-header-dir and win-source-dir. Make sure to use backslash for Windows paths or Dolly will throw an error when generating the project.

mac-id-header-dir="../../../source/sdksamples/myplugin"
mac-source-dir="../../../source/sdksamples/myplugin"
win-id-header-dir="..\..\..\source\sdksamples\myplugin"
win-source-dir="..\..\..\source\sdksamples\myplugin"

Even though we’re defining paths for source and header files twice, Dolly will create just one copy of each file. If you’re using Windows, Dolly will not create files in directories defined for Mac and vice versa.

The last changes we’re going to make are prefix-id and short-name. We’ll also set the type of our plug-in. The prefix-id of a plug-in is the ID value that InDesign will use to identify our plug-in. It is used to determine IDs of the boss classes, implementations and interfaces in our project. It must be a hexadecimal value. For the purpose of this tutorial, let’s set it to “0xef190”. For your own plug-ins, you need to obtain a unique prefix-id from Adobe Developers Connection.

Change the value of short-name to “MP”, short for MyPlugin. This attribute is used to prefix project file names for your plug-in. Therefore, it is advisable to keep it short.

prefix-id="0xef190"
short-name="MP"

We’re going to set the type of our plug-in to kUIPlugIn. Make sure the letter I is capital or Dolly will create a model plug-in instead.

plugin-type="kUIPlugIn"

Generating MyPlugin

It’s time to use our XML file to generate MyPlugin project with Dolly.

Windows: DollyXs.bat -q myInputFile.xml
Mac: DollyXs.sh -q myInputFile.xml

Once we run the command, Dolly is going to generate source files in /source/sdksamples/myplugin/ as we specified in our XML file.
Screen Shot 2013-02-21 at 13.05.36

Same with the project files. Our Xcode MyPlugin project will be generated in /build/mac/prj and Visual Studio project will be in /build/win/prj .

Screen Shot 2013-02-21 at 13.05.00

Open either MyPlugin.xcodeproj or MyPlugin.sln and you’re done! You’ve successfully created an InDesign plug-in using Dolly.

Find out more

If you would like to know more about manipulating the XML input file or Dolly in general, be sure to read the Readme.txt located in /devtools/sdktools/dollyxs/. You can find more information on InDesign Plugin development in the getting-started.pdf in /docs/guides/.

We welcome questions and comments!

myInputFile.xml

<?xml version="1.0" encoding="UTF-8"?>
<code

author="Alex"
long-name="MyPlugin"
mac-debug-target-dir="../debug/sdk"
mac-id-header-dir="../../../source/sdksamples/myplugin"
mac-project-dir="/Users/Alex/Desktop/Adobe_InDesign_CS6_Plugin_SDK/build/mac/prj"
mac-release-target-dir="../release/sdk"
mac-sdk-dir="../../.."
mac-source-dir="../../../source/sdksamples/myplugin"
mac-target-type="i386"
product-type="kInDesignProduct, kInCopyProduct"
plugin-type="kUIPlugIn"
prefix-id="0xef190"
short-name="MP"
win-debug-intermediate-dir="..\objD"
win-debug-target-dir="..\debug\sdk"
win-id-header-dir="..\..\..\source\sdksamples\myplugin"
win-project-dir="/Users/Alex/Desktop/Adobe_InDesign_CS6_Plugin_SDK/build/win/prj"
win-release-intermediate-dir="..\objR"
win-release-target-dir="..\release\sdk"
win-sdk-dir="..\..\.."
win-source-dir="..\..\..\source\sdksamples\myplugin"
>
<vcproj-file/>
<rsp-cpp-file/>
<rsp-odfrc-file/>
<xcodeproj-file/>
<xcconfig-plugin-file/>
<xcconfig-plugin-debug-file/>
<xcconfig-plugin-release-file/>
<id-h-file/>
<id-cpp-file/>
<nostrip-file/>
<triggerresourcedeps-file/>
<factorylist-file/>
<rc-file/><fr-file/>
<enus-fr-file/>
<jajp-fr-file/>
<generate-menu/>
<impl-item impl-file="actioncomponent-impl-file" impl-id="kDollyActionComponentImpl" impl-name="DollyActionComponent"/>
<generate-dialog/>
<impl-item impl-file="dialogcontroller-impl-file" impl-id="kDollyDialogControllerImpl"
impl-name="DollyDialogController"/>
<impl-item impl-file="dialogobserver-impl-file" impl-id="kDollyDialogObserverImpl" impl-name="DollyDialogObserver"/>
<generate-panel/>

</code>

Using EVE for UI layout

The Adobe Express View Engine (EVE) is the recommended method of laying out UI widgets in InDesign dialogs. The main benefit of using EVE is that widget geometry is calculated for you, so that when you add or remove widgets to a dialog all of the other widgets are shifted automatically without you having to recalculate sizes etc.

Benefits of using EVE

  • Updating dialogs by adding and removing widgets is made easier because the layout of all widgets is adjusted for you.
  • Where text is different sizes on different operating systems you don’t have to worry about calculating extra whitespace.
  • English dialogs can be smaller because you don’t need to leave room for anticipated localised text, so your dialogs look good in all languages.
  • EVE automatically resizes text, buttons, checkboxes, radio buttons and drop-down lists so you needn’t worry about text being clipped.

A quick introduction to EVE

In order to use EVE widgets in your dialog definitions you’ll need to add an include to your FR file.

#include "EveInfo.fh"

This file is a very useful resource since it lists all of the EVE widgets which are available out of the box, so do have a look inside.

In order to have your dialog use EVE you’ll need to add WidgetEveInfo to its type definition.


type BscDlgDialogBoss(kViewRsrcType) : DialogBoss(ClassID = kBscDlgDialogBoss)
{
   WidgetEveInfo;
};

Finally you can change your dialog definition to use EVE by changing it to use EVE widgets and by adding the necessary EVE layout constants to the dialog itself (since you’ve now made the dialog an EVE dialog by adding WidgetEveInfo to its type definition).

Since all dialogs have an OK and Cancel button and some other content, here’s a complete dialog definition that uses EVE to layout an OK and Cancel button.


resource BscDlgDialogBoss (kSDKDefDialogResourceID + index_enUS)
{
   __FILE__, __LINE__,
   kBscDlgDialogWidgetID, // WidgetID
   kPMRsrcID_None, // RsrcID
   kBindNone, // Binding
   Frame(0,0,388,112) // Frame (l,t,r,b)
   kTrue, kTrue, // Visible, Enabled
   kBscDlgDialogTitleKey, // Dialog name
   {
      // Add dialog content here (like EVEStaticTextWidget..)

      EVEGenericPanelWidget
      (
         kInvalidWidgetID, // WidgetId
         0 // RsrcId
         0,
         kBindNone, // Frame binding
         Frame(0,0,0,0) // Frame is 0 for auto-sizing
         kTrue, // Visible
         kTrue, // Enabled
         kEVEAlignLeft | kEVELargeSpaceAfter | kEVEArrangeChildrenInColumn,
         {
            EVEDefaultButtonWidget
            (
               kOKButtonWidgetID, // WidgetID
               kSysButtonPMRsrcId, // RsrcID
               kBindNone, // Binding
               Frame(0,0,0,0) // Frame (l,t,r,b)
               kTrue, kTrue, // Visible, Enabled
               kSDKDefOKButtonApplicationKey, // Button text

               kEVELargeSpaceAfter,
            ),
            EVECancelButtonWidget
            (
               kCancelButton_WidgetID, // WidgetID
               kSysButtonPMRsrcId, // RsrcID
               kBindNone, // Binding
               Frame(0,0,0,0) // Frame (l,t,r,b)
               kTrue, kTrue, // Visible, Enabled
               kSDKDefCancelButtonApplicationKey, // Button name
               kTrue, // Change to Reset on option-click.
               
               kEVELargeSpaceAfter,
            ),
         } // End of EVE Generic panel child widgets
      ), // End of EVE Generic panel widget definition

   },
   
   kEVEArrangeChildrenInRow | kEVESmallMargin,
};

If you are familiar with InDesign plug-in development you’ll notice that the general format of the dialog definition is the same as usual except for some EVE layout additions and the use of widget names prefixed with EVE.

How do I convert my existing dialogs to use EVE?

The InDesign plug-in SDK includes an EVEConverter tool which enables you to very quickly EVE-ize your dialog definitions however it’s output is less than optimal. Be aware that the tool will also convert any panel definitions to use EVE so you should keep a backup copy of your original FR file so that you can replace the EVE-ized panel definition with your original non-EVE panel definition. The EVEConverter tool is a great first step to get a feel for EVE and how to use it.

Once you are better acquainted with EVE it becomes easier to hand craft your conversions or do some of them by hand. It all depends on how complex your dialogs are and if you are using any custom widgets. As a rule of thumb you might use the EVE converter first, then go over the output by hand to remove any excess spacer widgets or superfluous generic panel definitions.

The plug-in SDK also includes a porting guide which includes a chapter on using EVE. You can obtain the plug-in SDK from here http://www.adobe.com/devnet/indesign/sdk.html.

Running a script from an InDesign plug-in

Perhaps you’ve come to native plug-in development from a more script-based background, or perhaps you have some existing script code you want to reuse in a new plug-in project. Whatever your background, it’s really handy to be able to run a script from a native plug-in, and it’s also surprisingly easy.

The code below works out of the box so you can copy and paste as much as you please.

#include "IScriptManager.h"
#include "IScriptEngine.h"
#include "IScriptRunner.h"
#include "IScriptUtils.h"
#include "JavaScriptID.h"

InterfacePtr<IScriptManager> scriptManager(Utils<IScriptUtils>()->QueryScriptManager(kJavaScriptMgrBoss));
if (!scriptManager)
{
   return;
}

InterfacePtr<IScriptEngine> scriptEngine(scriptManager->QueryDefaultEngine());
if (!scriptEngine)
{
   return;
}

InterfacePtr<IScriptRunner> scriptRunner(scriptEngine, UseDefaultIID());
if (!scriptRunner)
{
   return;
}

RunScriptParams params(scriptRunner);
scriptRunner->RunScript("alert('hello, world!');", params);

The above code uses JavaScript but you may use any script manager you like, including kAppleScriptMgrBoss for AppleScript and kOLEAutomationMgrBoss for Visual Basic. For a complete list of available scripting managers see ‘Script managers’ in chapter 10 ‘Scriptable Plug-in Fundamentals’ of the Programming Guide Volume 1 included in the plug-in SDK (available at http://www.adobe.com/devnet/indesign/sdk.html).

InDesign Server / OmniORB and Upgrading to Mac OS 10.6

Here’s a nugget that will be of interest to those of you who regenerate Java/CORBA support for InDesign Server on the Mac. If you upgrade to Mac OS 10.6, you must rebuild the OmniORB tools with an x86_64 target to ensure that they run correctly. Setting up the OmniORB tools is coverred in Regenerating the Adobe InDesign CS4 Server Java API. You should get the x86_64 target by rebuilding the tools on the upgraded machine.

Flash UIs with InDesign CS4

InDesign user-interface development can be expensive. It takes a lot of effort to implement a dialog or panel in ODFRC. Things should improve in future versions, with the possibility of using Flash-based user-interface tools like Flex and FlexBuilder. While this represents the future direction of InDesign user-interface development, there is a present reality in InDesign CS4. With an understanding of the current situation, you can implement Flash-based user-interfaces for InDesign CS4.

Continue reading…

Scripting InDesign CS4 Preflight

We’ve received numerous requests for sample scripts that demonstrate working with the Adobe InDesign CS4 new live preflight feature. Several of these requests have come from InDesign Server partners who want to know how to use the new preflight engine. My Creative Suite Developer Technologies teammate Joe Stinson and I collaborated on the following information that we think will save you a lot of time when trying to script the new preflight feature.

If you are not familiar with preflight, please first watch this introductory video:
http://www.adobe.com/designcenter/indesign/articles/lrvid4025_id.html).

This post will demonstrate how to interact with the preflight system using JavaScript. For illustration purposes, we show how to configure preflight to raise an error if the page size is something other than letter size (8.5”X 11”). We briefly highlight how it’s done in the UI, then show how to achieve the same results through scripting.

Continue reading…

Validating IDML Based Files

IDML is designed to be generated and manipulated by XML tools and programmers. To support this, IDML can be validated against a RelaxNG schema.

When it comes to schemas and validation, there are two types of IDML files:

  • There are many single-file variants (snippets, assignments, ICML, etc.). These files need to be validated with the snippet schema.
  • Packages are multi-file ZIP archives that represent an entire InDesign document. Packages need to be validated with the package schema.
    For more information on IDML files see the “IDML File Types” post.

Generating Schema Files

IDML can be extended by the scripting support in third-party plug-ins. For this reason, the schema used for validation must match a plug-in configuration. Rather than providing a static schema, InDesign provides a means to create a schema from your plug-in configuration. The following sample code demonstrates producing snippet and package schemas with JavaScript.

// Generate a non-package schema
app.generateIDMLSchema(Folder(“/idml-schema/snippet”), false);

// Generate package schema
app.generateIDMLSchema(Folder(“/idml-schema/package”), true);

This snippet schema is used to validate all single-file variants of IDML. It comprises two files:

File Purpose
datatype.rnc Shared data type file included by all schema files.
IDMarkupLanguage.rnc Validates all single file IDML variants (ICML, IDMS, ICMA, etc.).

 

The package schema comprises one shared file and schema file for each type of XML file that can appear in an IDML package:

File Purpose
datatype.rnc Shared data type file included by all schema files.
designmap.rnc Validates designmap.xml
MasterSpreads/MasterSpread.rnc Validates all master spread files in the MasterSpreads directory.
Resources/Fonts.rnc Validates Fonts.xml.
Resources/Graphic.rnc Validates Graphic.xml.
Resources/Preferences.rnc Validates Preferences.xml.
Resources/Styles.rnc Validates Style.xml.
Spreads/Spread.rnc Validates all spread files in the Spreads directory.
Stories/Story.rnc Validates all story files in the Story directory.
XML/BackingStory.rnc Validates XML/BackingStory.xml
XML/Mapping.rnc Validates XML/Mapping.xml
XML/Tags.rnc Validates XML/Tags.xml

Finding Errors in IDML

For demonstration purposes, we need files that contain errors. Imagine the following IDML fragment in both a snippet file (test.idms) and package (test.idml) file. The IDML contains four fairly obvious errors; try to spot all four.

<Spread>
<Rectangle foo=”Test” Self=”uec” …>
<RectData>…</RectData >
<Propertie>…</Propertie>
</Spread>

You may have found it difficult to spot all four errors. Imagine if this was buried in a huge XML file. Instead of trying to find errors ourselves, we use schema validation.

Schema Validation Basics

A RelaxNG schema can be used to verify the structural correctness of a document. It checks to make sure all XML nodes (elements, attributes, text data, etc.) are used at the right places in the document. It detects any unknown or unexpected nodes and ensures that required nodes are present.

InDesign’s RelaxNG schemas can be used to check the structure of a document; however, it does not check the content of these nodes. For example, it doesn’t check that all IDML references exist. It’s possible to do some non-RelaxNG-based error detection. This is discussed in “Additional Error Detection” below.

You can validate IDML files with any software that supports the compact form of RelaxNG. For snippet files, this is relatively straightforward: it amounts to pointing whatever validation engine you are using to the IDMarkupLanguage.rnc file (which includes the datatyps.rnc file).

Validating packages is more complex; there are two difficulties:

  • Packages are ZIP archives, and most RelaxNG validation engines don’t deal with ZIP files.
  • An IDML package comprises many XML files. The package schema comprises several schema files: there is one schema for each type of file that can appear in an IDML file. To validate a package, you need to match each XML file with its appropriate schema file.

Validating with IDMLTools

The InDesign CS4 Products SDK includes a Java package called IDMLTools. This package contains a validation application based on the Jing RelaxNG Validator, which handles both snippets and package files. It’s especially handy for package files, because it unzips the files and matches XML files to the appropriate schema file.
For information about setting up IDMLTools, see the IDML ReadMe. This amounts to the following:

  • Add the IDMLTOOLS_HOME environment variable. This should contain the path to your IDMLTools folder. (Do not terminate with a trailing \ or /.)
  • Add /bin to your search PATH environment variable. This provides easy access to the validation script.

Once set up, you can validate files by running the appropriate platform script, validate.bat on Windows and validate.sh on Mac OS. These scripts set the appropriate Java classpath and run the validation application. The validation application can be used to validate both types of IDML files (snippets and package files). Running the platform scripts with no arguments produces the following usage message:

Validator SchemaPath PackagePath [PackagePath...]

This means you validate by specifying a path to the schema folder, followed by paths to one or more package files that you want to validate.

Validating a Snippet

To validate the test.idms snippet, specify the path to the snippet schema, followed by the path to the actual snippet:

validate.bat “c:\idml-schema\snippet” test.idms

The validation application writes errors to standard error. Here are the results from validating test.idms:

Test.idms:143:10: error: required attributes missing
Test.idms:144:527: error: attribute “foo” not allowed at this point; ignored
Test.idms:145:14: error: element “RectData” not allowed in this context
Test.idms:146:15: error: element “Propertie” not allowed in this context

Validating a Package

To validate a package specify the path to the package schema, followed by the path to the IDML file:

validate.bat “c:\idml-schema\package” test.idml

The validation application unzips the archive to a temporary directory, validates each file against the appropriate schema file, then writes any errors to standard error.

Here are the results written when validating test.idml:

Spreads\Spread_ubd.xml:3:245: error: required attributes missing
Spreads\Spread_ubd.xml:27:527: error: attribute “foo” not allowed at this point; ignored
Spreads\Spread_ubd.xml:28:14: error: unknown element “RectData”
Spreads\Spread_ubd.xml:29:15: error: unknown element “Propertie”

Notice that the XML file containing the error is reported on the left. In this case, the error is in the Spread_ubd.xml file. Because package validation deals with multiple XML files in one pass, error results can come from several files.

Interpreting the Results

From the results above, we can deduce the four errors:

  1. The Spread element is missing a required attribute. Unfortunately, Jing does not report which attribute is missing, but it is easy enough to look at the schema or Adobe InDesign CS4 IDML File Format Specification and determine that it is the Self attribute that is missing.
  2. There is no “foo” attribute on the Rectangle element.
  3. “RectData” is not a child of the Rectangle element.
  4. Rectangle does not have a child element called “Propertie.” Looking at the schema, Adobe InDesign CS4 IDML File Format Specification, and numerous other examples, we can conclude that this element should be called “Properties” (with an ‘s’).

Additional Error Detection

The IDMLTools validation application includes some non-RelaxNG-based error detection. Currently, it checks for the following errors:

  • Missing designmap.xml file.

  • Missing or improper processing instruction at the top of the designmap.xml file.

  • Missing package files included in designmap.xml; e.g., Spreads/Spread_ubd.xml in the following output:

Because Adobe distributes the source for IDMLTools, it’s possible to add additional error detection. You’ll find the code for these items in the Validator.preVerifyPackage() method.

IDML File Types

IDML (InDesign Markup Language) is an XML-based format, introduced in Adobe InDesign CS4, for representing InDesign content. IDML is used in several InDesign and InCopy file types:

  • IDML files (or packages) are ZIP archives, containing numerous XML files. The entire set of these files represent a complete InDesign document. The files in an archive are described thoroughly in Adobe InDesign CS4 IDML File Format Specification. IDML files are identified by the *.idml file extension.
  • Snippets are IDML-based files that describe a subset of an InDesign document. They are not archives, but single XML files that contain IDML. The application UI, scripting facility, and plug-in API allow you to export snippets from InDesign. Most commonly, such a snippet represents a page item or group of page items. These type of snippets usually are identified by the *.inds file extension.
  • ICML (InCopy Markup Language) files are a special type of snippet. An ICML file represent s a single InCopy story using IDML. ICML files use the *.icml file extension.
  • InCopy assignment files are another type of IDML snippet. They are used to allow multiple writers to work on one InDesign document. Assignment files use the *.icma extension.
  • There are other features that leverage IDML; for example, exporting preflight profiles produces an IDML-based file.

InDesign Flash Export with C++

InDesign CS4 adds the ability to export pages to Flash (SWF and XFL files).

The following is a 10 page InDesign CS4 document exported to SWF (Flash). 

You can turn the pages by clicking the text “Next”.  This text was converted to a button in InDesign.  After the first page you will also see a “Previous” button.

More interesting, you can use drag and drop to turn the pages as if you’re turning the pages of of a book or a magazine.  To turn the pages using drag and drop do the following: 

  1. Hover the mouse cursor over the top right corner of the blue rectangle and drag it to the left.  You should see the page curl.
  2. Click and drag to the left.
  3. Release the mouse button when the page appears close to having turned.

If you need to export SWF from a plug-in, take a look at the ExportDynamicDocument code snippet in the InDesign CS4 Products SDK.  The above SWF was exported using that code snippet.

Note: We added a few enhancements (XFL export, and output file selection) in the 6.0.1 update.

The source file lives in the following location in the InDesign CS4 Products SDK.

  SDK/source/sdksamples/codesnippets/SnpExportDynamicDocument.cpp

The code snippet does the following in C++.

  1. Creates a 10 page document.
    • The pages dimensions are small to create the desired SWF size.
    • At 100% scale this is 72 pixels per inch
  2. Creates two text frames on the master pages and converts them both to buttons.
  3. Adds appropriate events (back and next) to these two buttons.
  4. Exports to SWF or XFL.

This last step demonstrates processing the kSWFExportCommandBoss and kXFLExportCommandBoss commands.

It’s more likely you would use scripting to build and export SWFs.  I anticipate adding an equivalent scripting sample in the near future.

 

InDesign SDK Blog

I’m starting an InDesign SDK blog… The idea is that we will use this blog to make announcements and publish simple samples. That is my hope anyhow. I have to learn how to use the software though. So, this is more or less my “Hello World” posting.

Thanks,

Heath Lynn
Creative Suite Developer Technologies
Adobe Systems