Home
eMail

If you're seeing something other than Verdana, the Font is Graublau Sans Web by FDI fonts.info

Creating Custom PDF Portfolio Layouts
Updated 11/13/2009

Part 2: Previewing Files and Navigating Folders

This article explains how to add the necessary code to your Navigator to make it actually do something interesting with the content of a PDF Portfolio. There are four concepts you'll need to understand and some code that goes with each.

What You'll Need to Get Started:

The following is a list of software that you'll need to get started with these tutorials. This section is repeated in each article on this topic.

What You Need: Where to get it:
Adobe Acrobat 9 Pro or
Adobe Acrobat 9 Pro Extended
If you don't already have a copy of Acrobat, you can buy it here. For Windows users, you can download a fully functional 30 day trial here. Sorry - we don't have a trial version for OSX.

Flex Builder 3 You can purchase or download a 60 day free trial of Flash Builder 4 here

Note: The Actobat ActionScript API (AcrobatAPI.swc) only works with version 3.0.0 of the Flex SDK. You can download version 3.0.0.477 of the Flex SDK here. The project files in these tutorials will be looking for the name "Flex 3.0.0" in the compiler settings.
The Acrobat 9 ActionScript SDK You can download the complete Acrobat 9 SDK here. The Navigator SDK is part of that.
Apache Ant Again, I like to keep everything in Flex so I use Flex Ant Tasks to zip my files into a Navigator .NAV file. Instructions on how to set this set up are in the next part of the series.

Files versus Folders:
Using the Acrobat ActionScript API to work with a PDF Portfolio or the "Collection", a file and a folder are both "IAttachments". If the "isFolder" property of the IAttachment is true, then the IAttachment is a folder and has an IList of additional IAttachments as it's children. A file has no children.

All of the Acrobat default Navigators treat folders and files the same for display purposes in that folders are listed right along side files and both are sorted together.

With the Acrobat default Navigators, you "activate" an item by double-clicking. Double-clicking on a file will preview that file and double-clicking on a folder will open that folder and display it's contents.This is a pretty intuitive approach since it mimics how people interact with files and folders in their operating system. In the example project for this article, I'll be using that same metaphore but you don't necessarily need to do so with Navigators that you develop.

You'll see a little later in this article how I use the itemDoubleClick event of my DataGrid to activate an item and then branch my code accordingly if the isFolder property is true or false.

Folder Navigation:
Along with the folder concept, you'll need to figure out how you want to allow users to navigate through the folder hierarchy. In the Acrobat default Navigators, folder navigation is provided through a "breadcrumbs" metaphore. Folder names and your path through the folders are displayed in the upper left of the Navigator window. I won't actually be using this metaphore, instead, I'll simply add an "up" button to return to the parent of the current folder and deactivate the button when the user is at the root of the PDF Portfolio. Once you understand the underlying code, you can program your Navigator to use whatever UI metaphore you like. This is where the binding statement I discussed in the previous article really comes in handy. You'll see in the example project that I simply set the dataSource property of the DataGrid to the currentItems object. The binding statement adjusts the contents of the currentItems object anytime the folder changes.

Preview vs Open:
The PDF Portfolio concept was developed to provide an easy way to deliver a collection of files in a compact, easy to navigate package. One of the features of the PDF Portfolio Navigator window is the ability to "Preview" a file. When you are previewing a PDF file, all of the interactive features, like forms fields, links, and multimedia, are fully functional but you don't see the full set of Acrobat or Reader tool bars; instead there is a clean UI that's perfectly suited to navigating the file.

From this preview mode, you can optionally "Open" the file into a normal Acrobat window if you need to do additional work on the file like comment, redact, do form authoring or use the touch up tools. For security reasons, a Navigator can only preview files, it cannot open them. However, your Navigator can detect if a file that is part of your PDF Portfolio is opened in a regular Acrobat window (see image to the right).

Next and Previous:
When your Navigator causes a file to preview, you'll also want to set the next and previous properties of Acrobat. When either the selection or the sort order changes, the Navigator's definition of what the next and previous files should be may change. You'll need to add some code so that the next and previous buttons in the upper left of the preview window function properly.

Instrumenting the Double-Click:

To begin, I'll create the functions that do the heavy lifting every time an item is double clicked.

"Preview" is one of three commands that you can execute on an IAttachment. As I mentioned earlier, a Navigator can't directly interact with any of the PDF Portfolio attachments. To preview a file you need to go through the ICommand interface. This interface provides functions used to request and execute commands. A command is a request that Acrobat perform an action on the Navigator's behalf. Normally the Navigator cannot perform the action directly because it requires access to secure data that is either not available to it or it must display user interface elements, such as dialogs or context menus. The "host.requestCommands" method requests a set of named ICommand instances. The requested ICommand instances will be added to the commands property which lets you actually use the command. While that may seem a little convoluded, in practice, it's just a little code that you can write once and then simply copy from project to project.

I'll begin by adding the "preview" ICommand to the commands property of the host object. Look at the example project to see this code in context.

			
      _host.requestCommands([CommandType.PREVIEW]);

Then I'll add a "preview" function so that previewing a file is easier and all I need to do is pass an IAttachment to the function. A file must be selected before it can be previewed so I need to set the selection property of the _host object. I'll discuss the "updatePrevNext()" function a little later in this article.

    public function preview(attachment:IAttachment):void
    {
        if(_host.commands.hasOwnProperty(CommandType.PREVIEW))
        {
            var previewCommand:ICommand = _host.commands[CommandType.PREVIEW];
            _host.selection = [attachment];
            updatePrevNext();
            previewCommand.execute(attachment);
        }
    }

Next, I'll add the code that branches based on whether it was a folder or a file that was double-clicked. If the item is a folder, I can simply set the currentFolder property of _host object and the magic binding statement does the rest.

			
    import mx.events.ListEvent;			
    public function itemDoubleClicked(event:ListEvent):void
    {
        var itemIndex:int = event.rowIndex;
        var item:IAttachment = IAttachment(currentItems.getItemAt(itemIndex));
        if (item.isFolder)
            {
                _host.currentFolder = item;
            }
        else
            {	
            preview(IAttachment(currentItems.getItemAt(itemIndex)));
            }		
    }
  

So, I just added a way for the users to navigate into a folder. Now I need a way to let them get back out. I use the fact that the "currentFolder" property of the root of the PDF Portfolio is null to set the "enabled" property on the button. Then the "upFolder" function simply sets the currentFolder property of the _host object to be the parent of whatever the currentFolder is.

<mx:Button label="Up Folder" enabled="{Boolean(_host.currentFolder)}" click="upFolder()"/>

      private function upFolder():void
      {
          if (_host.currentFolder)
              {
              var item:IAttachment = _host.currentFolder.parent;
              _host.currentFolder = item;	
              }
      }
            

Finally, I add the "updatePrevNext" function. It's more code than is usefull to show on this page. Instead, you can take a look at it in context in the example project. The important part is that in order for the next and previous buttons to continue to work after a user moves off of the file that you preview, you need to add a "selectionChanged" event listener to the _host object. In my example, the "selectionChanged" event listener function just calls the updatePrevNext function.

			
_host.addEventListener("selectionChanged", selectionChangedHandler);

      private function selectionChangedHandler(event:Event):void
      {
          updatePrevNext();
      }			
            

Detecting and Showing which Files are Open:

Detecting and showing which files are open needs to occur independently of any user action in your Navigator because a file could have been opened when the user was in the list view or when another Navigator was being used. In order to detect when a file has been opened, you need to listen for an "isOpenChanged" event. In my DataGrid for this example project, I added a second column that will display true when a file is open or false when it's not. Basically, I'm just using the string value of the isOpen boolean property of an IAttachment. My labelFunction for that column is the isItOpen function which also adds the listener for that item. When the listener gets triggered because a file has been opened, the DataGrid properties need to be updated. In this way, my DataGrid will display which files are open when it starts up and can respond to events while it is running.

			
      private function isItOpen(item:Object, column:DataGridColumn):String
      {
          IAttachment(item).addEventListener("isOpenChanged", refreshOpenedFiles)
          return IAttachment(item).isOpen.toString();
      }
      
      private function refreshOpenedFiles(event:Event):void
      {
          itemList.invalidateList();
          itemList.validateNow();
      }
            

Conclusion:

And that's it. You've now got the basics of previewing files and navigating folders. The DataGrid is the simplest of controls but the basics of this Navigator can easily be applied to just about any data driven control. In Part 3, I'll discuss how to add thumbnails for the various attachments.

After downloading this example and compiling the code, you can install the Navigator by following these simple steps.

Installation:

Windows:

  1. From Windows, select "Start" then "Run". Paste the following line into the text box and press enter

    %USERPROFILE%\Application Data\Adobe\Acrobat\9.0\

  2. Create a directory called "Navigators" if you don't already have one
  3. Drag the "_01_HelloWorld.swf" file to the "Navigators" directory
  4. Restart Acrobat if it's running.
  5. In the "Edit PDF Portfolio" panel you should see an "Other Layouts" category in addition to "Basic Layouts"
OSX:
  1. Browse to /Application Support/Adobe/Acrobat/9.0_x86 in your user Library folder
  2. Create a directory called "Navigators" if you don't already have one
  3. Drag the "_01_HelloWorld.swf" file to this location in Finder.
  4. Restart Acrobat if it's running.
  5. In the "Edit PDF Portfolio" panel you should see an "Other Layouts" category in addition to "Basic Layouts"

Files:
Download Source

Comments: