Sam Williams


7 April 2008


User level
Required products
Flash Builder (Download trial)
Sample files (13742 KB)

Additional Requirements

In this article I will describe the process for developing a Flex/Cairngorm application for viewing images (see Figure 1). The application itself is small. I originally developed this project as a demonstration showcase for potential employers. My goal was to develop an app small enough to talk through at an interview while also demonstrating my understanding of the Flex framework and Cairngorm.
Figure 1. The image viewer application
Figure 1. The image viewer application

The application consists of an image viewer component that toggles its method of display at runtime from displaying the images in a grid to a slideshow presentation. The data for the application is provided in an XML file. In addition to the image source URL data, the XML file also contains a creation date for each of the images. The image viewer application allows the user to sort the images alphabetically or by the date created, resulting in a dynamic re-ordering of the images in either the grid or slideshow mode of display.

Using Flex with Cairngorm

Flex is an important addition to the RIA space. It provides a rich API for building complex rich Internet applications, making the process of developing significantly more efficient and enjoyable. Since Flex applications are deployed via Flash Player, they are inherently cross-platform and available to almost every computer connected to the Internet. Cairngorm is a framework for building complex RIA's with Flex that utilizes several concepts of core J2EE patterns. Cairngorm has a large adoption within the Flex developer community—making it a particularly valuable skill for an independent developer. Like any good framework, Cairngorm facilitates a very predictable development process, which allows developers to confidently update and add new features to an application. Cairngorm is also very helpful for team development projects because it promotes the separation of functionality within an application, allowing multiple developers to work in parallel. It is an established, well-proven solution.
Structuring the application
When building Flex applications with Cairngorm, I begin by setting up the structure of the application. This allows me to focus on utilizing this structure whenever I'm adding new features. To start this project, I created the Model Locator. This is just a Singleton which implements the com.adobe.cairngorm.model.IModelLocator marker interface. Its function is to provide a central storage and access point for the application data and domain.
Since the data for the application comes from an external XML file, both the Service Locator and the Business Delegate patterns within the Cairngorm framework are utilized.
The Service Locator is a Singleton, usually extended with MXML, containing all of the services the application uses. The application itself only contains an HTTP service pointing to the URL of the XML file.
The Business Delegate abstracts the specifics of calling various services away from the main business logic. Since the image viewer application has one service, it only requires one Business Delegate. The Business Delegate has a function called getData. When this method is called, the XML file is loaded and an ArrayCollection of value objects is created from its contents.
The first Command class that is required is executed when the application starts. It calls on the service defined within the Service Locator via the Business Delegate. Once it receives the results, it simply updates the ArrayCollection in the ModelLocator with the one received from the Business Delegate.
At this point, the only thing the application can do is load in some XML. However, by setting things up this far, a large amount of the application's structure is already in place. Here's a summary:
  • The Model Locator contains an ArrayCollection of image value objects.
  • The Service Locator and Business Delegate implementations define the service (the XML file) and encapsulate its loading.
  • The Command class calls a method within the Business Delegate and updates the model with the result.
  • The Front Controller registers the one command to an event. The event fires when the application loads, causing the data to be immediately loaded.
The image viewer component
Now that the data is loading and populating the model, the next step involves constructing the image viewer component.
In order to add a little eye candy to the app, I decided to make the images animate into position when sorting and toggling between the two display modes (from grid layout to slideshow). To provide this functionality I created two interfaces, IItemView and IItemDisplayer. The first, IItemView, requires just three functions. Two functions perform the operations of getting/setting the data provider, and one function performs the setting of an IItemDisplayer. The IItemDisplayer is an interface that contains a single function named display. The two interfaces work together via composition. The IItemView delegates the work of displaying the items that it contains to its IItemDisplayer. Changing the way the items are displayed is simply a matter of setting a new IItemDisplayer. Here's the code:
package { import mx.collections.ArrayCollection; public interface IItemView { function set itemDisplayer ( itemDisplayer : IItemDisplayer ) : void; function set dataProvider ( value : ArrayCollection ) : void; function get dataProvider () : ArrayCollection; } } package { import mx.collections.ArrayCollection; import; public interface IItemDisplayer { function display( items : ArrayCollection , unscaledWidth:Number, unscaledHeight:Number, selectedItem : IItem ) : void; } }
There are three implementations of these interfaces that make up the component: one of the main IItemView and two of IItemDisplayer. The implementation of IItemView is a UIComponent that serves as the base of the image viewer. It is instantiated in the main entry point of the application via MXML. The two IItemDisplayers are also created in this main entry point and they are assigned to the ItemView when it fires its various selection events.
The code example below contains some of the key functions from the ItemView component class. There are two setter functions. One sets the IItemDisplayer and the other sets the data provider (which are both required by the IItemView interface). The last two functions are more interesting. The display first checks to see if an IItemDisplayer has been set. If it has, the display function within the IItemDisplayer is invoked. The items are displayed according to its implementation. For this example, I've overridden the UIComponent method updateDisplayList, so that the images can resize with the browser window if the user changes it.
public function set itemDisplayer ( itemDisplayer : IItemDisplayer ) : void { _itemDisplayer = itemDisplayer; display(); } public function set dataProvider ( data : ArrayCollection ) : void { _items = data; addChangeListeners(); } public function display () : void { if ( _itemDisplayer != null ) _itemDisplayer.display( _items , unscaledWidth , unscaledHeight , _selectedItem ); } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { display(); }
Sorting the images
At this point, the image viewer application performs most of its functionality. It loads in data from an external source and displays the data in an animated display mode that can be changed at runtime. When I was building the application and I got to this point, I decided that I wanted to demonstrate more user gestures and more of the Cairngorm workflow. I chose to add a sorting option because I was confident it would fit neatly into the existing functionality that animates the positions of the images. Once the basic structure of a Cairngorm application is set up, the process of adding new features is straight-forward and follows a repeatable and consistent pattern.
Here are the steps I followed:
  • Create the command class
  • Register the command to an event in the Front Controller
  • Create the view which dispatches the event
Following this pattern, I created two new command classes, which perform the task of sorting the value objects stored in the model by either URL or the date created. I registered both these commands to the SnappyController (the name I gave to the front controller in this app) and created a combo box that fires the necessary Cairngorm events when the selected item changes.
And, that concludes the development process... Since the view is listening for changes in the model, the view is updated and animated each time the data is sorted.

Where to go from here

I hope this article has given you a taste of the possibilities available when you develop applications with Flex and Cairngorm. Using relatively little code, it was easy to create an extendable image viewer component that plugs neatly into the framework. To find out more about working with Flex and Cairngorm, see the following online resources:
Also, to observe Flex code in action, try the Interactive Cairngorm Diagram Explorer.