Author Archive: James Boag

Using InDesign Array Collection Objects in ActionScript

At last week’s Adobe MAX, I got talking to an extremely talented InDesign developer with a complaint; in ExtendScript InDesign exposes array collections of objects in response to certain calls, but the CS SDK doesn’t allow for navigating these.

It’s an interesting point, and one with a little back story. What InDesign actually does is always return an object (e.g., a TextFrame); that object’s properties may then be for a single item, or a number of them (in which case every property you access on that object is actually an array). To the scripting DOM, though, both register as the same type (a TextFrame), and there is no way to know ahead of time what InDesign will return for these.

This is great for a language with weak typing, like ExtendScript, but poses challenges for how to represent that in a strongly typed environment, like ActionScript.

Fortunately, there’s a workaround that allows you to make use of these without having to call out to ExtendScript code; the host object delegate.

This is the core representation of the scripting element that the application returns, and so we can call any API on it that we choose. We lose the type-ahead in ExtensionBuilder, of course, and there’s the potential for runtime errors inherent in any untyped code, but it gives you a mechanism to use InDesign’s more advanced scripting DOM behaviour.

As an example, if you create a document with two text frames, assign the script label ‘test’ to both, and then use the code:


var myText:TextFrame = app.activeDocument.textFrames.item("test");
trace(myText.id);

This will generate a runtime error, because the call to ‘id’ will actually return an Array of Numbers, rather than the expected single Number.

To use the host obect instead, you’d simply change the code to:


var myText:HostObject = app.activeDocument.textFrames.item("test").hostObjectDelegate;
trace(myText.id);

You’ll now get both ids printed. Many properties and functions will work without this, but for times when that fails the HostObject provides an invaluable means of working around that.

Happy Coding!

James

Note: you may also want to set the script preferences version to work around an unrelated issue in InDesign with these functions not working in the 7.0 and 7.5 scripting versions. You can do that by inserting ‘app.scriptPreferences.version = “6.0”;’ ahead of the call (and a revert to 7.0/7.5 afterwards).

Drag and Drop in a Creative Suite Extension

One of the great benefits of working with the Flash/AIR environment, inside the Creative Suite, is how easy it makes tasks which would be significant challenges in C++. The geolocation sample is one example of this, but another is drag and drop.

This is something with a lot of potential benefit for developers, but (due to some limitations with the current environment) needs to be addressed in a specific way. To achieve this, we use the Flash NativeDragManager, triggered on a mouseDown listener added to our component like so:

<mx:FileSystemTree
id="fileSystemTree"
width="80%"
height="80%"
mouseDown="onFSTreeMouseDown(event)"
/>

We can then implement this listener to begin the drag:

public function handlePureFlashFileDragStart(event:Event):void
{
var clip:Clipboard = new Clipboard();
clip.setData(ClipboardFormats.FILE_LIST_FORMAT, event.currentTarget.selectedItems);

var allowedActions:NativeDragOptions = new NativeDragOptions();
allowedActions.allowLink = false;

NativeDragManager.doDrag(event.currentTarget as InteractiveObject, clip);
}

Here, we have the option of what kind of data we load onto the clipboard (in this case it is a collection of files), and also, if we so desire, we can add an Image object which would be used as the thumbnail for transfer.

If you’d like to see this in action, we’ve created a project which allows files to be dragged from a filesystem tree view into InDesign. It also allows text to be dragged from InDesign to a box in the extension, and back, using the same mechanisms. You can find that here.

For more information on Flash native drag and drop, you might like to look at the tutorial on the Adobe Developer Connection and the livedocs for the NativeDragManager.

Geolocation inside the Creative Suite

As part of the Creative Suite Developer Summit we’ve been showing off some sample code that illustrates just how easy certain workflows become when you move into Flash. One of these, that was shown at the session on Connecting the Creative Suite to Web Services (go here to watch), illustrates how you can connect up the Creative Suite to Google Maps and Flickr.

This sample shows an extension built to run in Photoshop, InDesign and Bridge CS5 (and could easily be extended to any product in the Suite). It connects to Google Maps to show location information, and Flickr to show relevant images – with the data used to power those searches customised based on the application the extension runs in. So, in Photoshop this will check the geolocation of the current image (extracted via XMP) and show the images taken nearby. In InDesign it will instead take the location from the machine’s IP address and search based on keywords using the user’s last sentence. Bridge provides a combination of both, where location comes from the XMP and the keywords come from the image tags.

The best part of this is how cheap integration is with these external systems. Google Maps Flex SDK, for example, requires a single MXML entry to create a map, with an additional call into that object being enough to change the positioning of the map;

<maps:Map xmlns:maps=”com.google.maps.*”
    id=”map” width=”263″ height=”229″
    url=”http://code.google.com/apis/maps/”
    key=”SUPER_SECRET_API_KEY”
    x=”30″ y=”10″/>

this.map.setCenter(location,15, MapType.NORMAL_MAP_TYPE);

For Flickr there are plenty of SDK options available, including one for ActionScript, but for the purposes of this I’ve chosen to roll my own calls. This uses a network communications library provided with Extension Builder, which lets us use the minimal amount of code to make a quick call across the network to retrieve the relevant data;

var request:HttpRequest = new HttpRequest(HttpRequest.GET, “http://api.flickr.com”, “/services/rest/”);
request.setParam(“method”, “flickr.photos.search”);
request.setParam(“api_key”, FLICKR_KEY);
request.setParam(“lat”, latLon.lat());
request.setParam(“lon”, latLon.lng());
request.perform(function(response:HttpResponse):void
{
    if (response.succeeded() || response.get_Status() == 0)
    {
        if (response.isParseable())
        {
            // success: XML or JSON response
            var xml:XML = new XML(response.getBodyText());
            for each (var photo:XML in xml.photos.photo) {
            }
        }
    }
});

If you’d like to try this out, you can grab the Extension Builder project here. You’ll need to drop the Google Maps Flex SWC (available here) into the libs folder, and enter your own API key for both the Maps service and Flickr.

I’ve also made it available as a ZXP (here), and as a zip for Bridge (here) the contents of which should be unzipped into your Bridge CS5 user startup scripts folder.

Welcome to the Creative Suite SDK Team Blog

Welcome to the Creative Suite SDK team blog. This will be
a channel for the people behind the Creative Suite SDK (available now from the Adobe Developer Connection), to keep in touch with developers and share interesting information and sample code with the community.

Over the next few days you can hear more about the CS SDK at the Creative Suite Developer Summit in Seattle. If you can’t attend the summit in person you can still get all of that information, as all of the panels will be available via Connect. For more on the CS Developer Summit please see the program at http://niemannross.host.adobe.com/2010csbuDeveloperSummit/conference/index.php

We’ll also be pushing as much of the content we show at the summit as possible out to developers through this blog and through Adobe Cookbooks. So lots of the cool demos we’ll be showing will be available in full code form here, along with explanations of how to write them from scratch.

Happy coding!

The Adobe DevTech Team