JustPaste.it

XML for UI Description in Flash MX

NOTE 1 - This article originally appeared shortly after the release of Flash MX (Flash 6). The supplied FLA will not work as written in Flash MX 2004 with AS2, though the concept of the article is still relavent.

NOTE 2 - Due to sice differences between the original article format and the current blog settings, some images may appear crappy. If you want to view the image properly, simply right-click on the image and select "View Image" from the context menu (or similar)

Unless you've been living under a rock for the last several years, you've no doubt been bombarded with the hype surrounding a simple, plain text technology named XML - eXtensible Markup Language. But even with the books, magazines, and web sites dedicated to XML, many developers still have no idea what XML really is, or even how they can use XML in their applications.

WHAT IS XML?

At its core, XML is simply a method of representing and communicating structured data in a logical, plain text format. Instead of being proprietary or in a binary form that only works on one software platform, XML can be read by any platform, software, or device that can read and parse text.

All data elements in an XML document are wrapped by "tags", which can be nested as deep inside each other to create the desired hierarchical structure. Before we go any further, let's look at a simple XML file that will give a better example of what this technology is. Imagine we need to pass data between an address book application and a word processor for mail merge functions. Our address book application could output the required information in XML like this:

FIGURE 1 - XML

Even without any sort of technical background, most people are able to understand the data and the implied hierarchy in this XML document. The power of such an obvious and simple technology may not be apparent at first. Once you realize that any software, regardless of platform or device can use this data, you'll begin to see it's potential. However, many developers don't look past the basic database replacement uses for XML. We are going to look at using XML in a way that some people never think of – integrating XML with Macromedia Flash MX.

WHAT IS FLASH MX?

Macromedia Flash has become the ubiquitous browser plug-in for web animation. According to Macromedia, the player is installed in 94% of all web browsers on the Internet. Flash uses ActionScript as its core programming language. ActionScript is an ECMA-262 based language – the same language specification as JavaScript – so many web developers will be immediately familiar with programming in Flash. Macromedia has incorporated XML capabilities in their Flash development tool since the release of Flash 5 in the fall of 2000. The parsing of XML inside Flash 5 was notoriously slow, and thus was often overlooked for other data handling methods. One of the highlights accompanying the introduction of Flash 6 (now called Flash MX) in March 2002 is the replacement of the old XML parser with one that is now 100 times faster than before, making XML inside Flash a very powerful tool. Rich data-centric applications built with a Flash front-end are now a reality.

OUR PROJECT

Our project will be a presentation/training application for our new, imaginary Point of Sale software. The presentation will be used internally for sales purposes, and externally to train end-users. Each target audience requires different content, and some clients would like the presentation to integrate with their corporate look-and-feel.

We are going to look at how we can use XML and Flash MX to represent not our content itself, but instead our user interface and the sequence of our content. We will build a small "shell" application in Flash MX that loads XML and creates a GUI on-the-fly, and navigates through an XML list of content "slides". This shell will be able to work for many projects without the need to recompile anything. Our application is deliverable via cd-rom, intranet or Internet. The only limitation is content size. Once complete, we will be able to change the look and feel of our application, as well as the flow of content, by simply changing our XML. For our application, this XML will exist as text files, though it just as easily could be retrieved from a database on a remote server.

If you are familiar with Flash from an animation standpoint, this project may look a little strange. All code either exists in separate, included ActionScript files, or resides entirely on the first and only frame of our main Flash movie. This article will focus on the interaction between our XML and Flash, without diving into every bit of code. Though the Flash application described in this article is a fully functioning presentation engine, it is meant more as a starting point for you to create bigger and better custom apps.

LET'S GO!

We’re going to jump right in and look at how we can use XML to describe our content. For this project, we will be presenting to the user a series of Flash-based animated tutorials, as well as individual static graphics (JPEG) with an optional accompanying audio file (MP3). As XML, we will describe this content, and the flow between sections as follows:

FIGURE 2 - Content XML

We open our XML document with a root node named "content." This is the "wrapper tag" for all of our content nodes. XML node names are completely user-definable and can be as descriptive as you need to describe your data. The nodes inside the root node are called child nodes in the hierarchy. In this case our child nodes are only one level deep and describe each step of our content.

We can see that for the default tutorial, we start with a static graphic image and accompanying audio. This is followed by two Flash movies, and completed by another static graphic with audio clip. Though this seems like a small amount of content, remember that each Flash movie could be anything you could do inside Flash – we aren’t just limited to slideshow-type presentations. Each Flash section could be an entire interactive emulation of software, an interactive video, a quiz, or even another shell application with its own content flow.

Each content node has a "title" attribute and a "filename" attribute. Graphic nodes have an additional attribute of "audio." The "title" attribute will be the text that displays on-screen to let the user know what section they are currently viewing. The "filename" attribute will point the Flash shell to the appropriate section content. Finally, the "audio" attribute is the optional filename of a MP3 file to play along with a static graphic (Flash movies can have audio built into them).

Now, as our content flow XML exists as a text file, we can add or remove sections at any time in the future. As an added bonus to this structure, we can programmatically determine how many content sections (child nodes) we have, so we don’t have to worry about hard-coding presentation length.

Flash provides a complete API for loading, parsing, creating, and saving XML. Reading this XML document into Flash is a simple task. Using ActionScript, we create a new XML object and load our content document into it using a load() function:

// create XML object
var contentXML = new XML();

// ignore carriage returns betweens lines
contentXML.ignoreWhite = true;

// specify function to call once XML is loaded
contentXML.onLoad = processContent;

// load the XML document into the XML object
contentXML.load("content.xml");

For our presentation, we will need to determine the number of sections we have, and put each section into an array of sections. The code for such a task looks like this:

function processContent(success) {

if (success) {

// fill content array
contentItems = this.firstChild.childNodes;

// set maximum number of content items
maxContentItems = contentItems.length;

// create the actual GUI
initGui();

} else {

trace("ERROR LOADING CONTENT XML");

}

}

This function is called once the document has been loaded and parsed by Flash. Flash will automatically pass a true/false value to the function (here called "success") that tells us whether there were any errors in parsing the XML. If we are successful in parsing the XML, we fill the contentItems array with the child nodes of our content, create a variable for the total number of content items, then call a function to create the GUI for our application. If we were not successful in loading and parsing the XML, we report an error. The trace() function only displays inside the Flash IDE, so for real-world applications, we would want to create a way to report the error to the user and exit gracefully.

As our content information now resides in an array of child nodes, moving through the content becomes a routine programming task. We can simply use a counter variable to keep track of where we are, and where we can move. Several functions exist in our application to move backwards and forwards through the content XML, handling each content type encountered. When called, showNextContentItem() and showPreviousContentItem() functions increment or decrement our counter and show the content item at that location in the array. Both functions include logic to turn on or off interface elements should we be at the beginning of the content, in the middle, or at the very end. (See "contentHandler.as" file)

Now that we know we can load and navigate through our content, we can look at our interface.

 

THE GUI

In most instances, the visual interface of an application has had to be hard-coded into the final executable. In some cases, it is created through code; in other cases, it is visually laid-out. Either way, once the application is compiled, changes to the GUI are neither easily made nor easily deployed. With a little bit of planning and good up-front requirements, we can program Flash MX to allow for the on-the-fly creation of any GUI element needed for our application. Even custom developed UI elements can be added to the screen at run-time, making customization fast and easy.

For our application, we will create methods to read an XML description of the GUI, and create the interface dynamically.

Before we look at the XML, let’s look at one version of our final GUI may look like:

FIGURE 3 - The GUI

From this screenshot, we can see that we have a background image, a main content area section, a text display of what section the user is looking at, and two navigation buttons – Back and Next.

Now let’s look at the XML that outlines this layout. Notice how well the XML describes the above screen. The readability of XML data is certainly one of the format's most appealing qualities. There is nothing cryptic about this code.

FIGURE 4 - GUI XML

As a description of our interface, our XML is pretty self-explanatory, however it also contains two nodes that don’t seem to represent anything visual. In fact, they don’t. The "textformat" node is a description of a text style that can be later used by dynamically created textfields – in this case, our section title textfield. Later on, when we look at the code to generate the GUI from the XML, we’ll see how our parser only recognizes specific nodes – background, button, content_area, textformat and textfield. The "_button" node is not a recognized node name, so it will be skipped when we create the interface. We can use unrecognized node names for elements that we temporarily want to remove from an interface, but could add back in at any time. If some of our users should not be allowed to go backwards through the presentation, we could simply rename the back button node to "_button" and only the next button would show up.

Just as we're able to create different content flows, we are also able to create separate layout XML documents for different scenarios. Since we'll be loading the graphics dynamically that make up the interface, we are able to "skin" or "theme" our interface to match different corporate needs; again, all without recompiling our main application.

Flash MX’s dynamic creation and loading of movie clips, images, audio, text fields, and text formatting, as well as programmatic drawing capabilities give us a firm foundation on which to build our interface rendering code. The basic premise of the process is that for each node type in our layout XML, we create an interface object of the same type. For each "button" node, we create an on-screen button; for each "textfield" node, we create an area on screen to store text, etc. In Flash our GUI will be built from the background up – layer upon layer. Lower layers are visually behind higher ones. For our presentation app, we will be parsing the XML in a top-down order, so we order the XML to have background layers at the top of the file, and foreground layers at the bottom. A graphic may help illustrate this concept better:

FIGURE 5 - Layers

CODE CODE CODE!

Let's look at the ActionScript needed to take our XML and create an interface. For example purposes, we'll only look at two element types – the content area and buttons. The complete code for creating our GUI is located in the "guiHandler.as" file.

Once we load our GUI XML, we start at the first child node and work our way down, branching for each node name. When we reach a "content_area" node, we know we'll be placing an area on screen that will contain our content. In Flash, an empty movie clip represents this area. Flash MX has the ability for us to create movie clips dynamically, but in our case we are attaching a pre-existing movie clip to the screen. This movie clip has a sub-movie clip that the actual content will be loaded into. Showing, hiding, moving, and rotating our content can all be applied to the parent content area, without concern of what is currently displayed, and our content happily inherits these changes. This content area is given a unique name in code that our content handling functions will use to load the content into.

In our XML, our content_area node only contains attributes for x and y screen locations. During our requirements gathering process, we had determined our content would be 400 pixels wide by 300 pixels high – a good size for both web delivery and cd-rom delivery. Knowing this, all content was created to these size specifications, so we only need to know where to put the content, now how big it is. In this case we've positioned our content area at 26 pixels to the right, and 24 pixels down, relative to the top left corner of the application's screen.

Now that we have our content, we need a way to let the user navigate through it. We can see from the GUI XML that there will be two buttons on screen – Back and Next. Like the content area, we only need to know where to position the buttons, and not concern ourselves with how big or small they are. Each button node also contains a "name" attribute. This name is what is used when we create the button in code, as well as what is passed to our button handler code (more on this later).

Normally in Flash, buttons have three states – up, over, and down. In most cases, this is sufficient. However, there may be times when we need a button that does a little more than this. Maybe it would be nice to have a disabled state, or a "hey look at me I'm blinking to get your attention" state. In the interest of meeting these needs in the future, our code is designed using a custom button made up of a movie clip with several frames of animation and some custom code. Each frame in our animation represents a button state, just like a normal button in Flash. The difference is that we can add as many frames as we need to fulfill all requirements. From a design standpoint, there is almost no difference between our method and the normal Flash button method.

From a coding perspective, this method is unlike anything else you may have done with Flash prior to MX. Flash MX now allows us to create classes – custom objects with methods and properties – and attach the classes to movie clips. Instead of having to create lots of redundant custom code for individual movie clips, we can simply create a class object and associate the class with any movie clip that needs the custom functionality. For those familiar with Object Oriented (OO) programming languages, ActionScript is not a true OO language, as it does not natively support inheritance or polymorphism, but it does get close.

Back to our buttons. Creating the buttons in code is almost identical to creating the content area. We attach a placeholder movie clip on stage at a specific location, and load the button graphics into a sub-movie inside the holder. The part that makes this all work as a button is that the movie clip we are attaching as a holder clip has a custom class associated with it. This class has the functionality to handle the same events as a normal Flash button, as well as custom functions to enable, disable, show, and hide a button. We can extend this class to handle any button state or event required, and automatically each created button will inherit the new code.

 

BUTTON, BUTTON, WHO'S GOT THE BUTTON?!

Besides handling the changing of the visual state of our buttons, our custom class also passes onRelease events through to a central button event handler. By doing this, we never have to attach logic code directly to a button. Let's take a quick look at how this is accomplished. In our custom button class code, we have the following code:

mcButton.prototype.onRelease = function() {

if (this._enabled) {

this.button_frames.gotoAndStop("over");
handleButtonDown(this._name);

}

}

This code simply says "if this button is enabled, change the button graphic to the 'over' frame, and pass the button's name to the handleButtonDown() function." The button's name is the name that is assigned in the XML file. The handleButtonDown() function branches to specific functions based upon which button name is passed in to it. This is the only place in our application that requires a bit of hard-coded logic. Our handleButtonDown() function needs to know what to do for any given button name. This is where a good set of requirements and future use considerations are important. You'll see in the accompanying code file "buttonHandler.as" that there is a condition for an Exit button (btnExit). This is an example where, at some point in the future, we feel we might require a specialty button to exit the presentation in the middle of the content.

 

PUTTING IT ALL TOGETHER

Now we have content we can use, and a dynamic GUI, we just need to package it all together into a cohesive shell application. In reality, there is not much more we have to do. What remains is a look at one more XML document, and at the sequencing of our XML loading and processing.

As mentioned earlier, our application is built so we can change the look and feel as needed, but up to this point, we've only discussed one set of XML documents for one specific theme. How do we let the application know which theme to use? Easy - before we can load any content or GUI XML, we need to load a "setup.xml" file:

FIGURE 6 - Setup XML

This very basic XML data will tell us the current version of our application, which can be used for debugging or distribution purposes, and lets the shell know which "skin" or "theme" to load for the GUI. We create a global function in Flash to create a "themed" filename based on this value:

_global.getThemedFilename= function(inItemName) {

return _global.theme + "/" + inItemName;

}

This function gathers the loaded theme value from the parsed setup XML, and returns the filename pointing to the appropriate theme folder. (You'll find this function the "globalFunctions.as" file). Obviously, if we were distributing our application on cd-rom, we would probably not include more than one theme. In the included code to this article, you will find two themes – the default "basic" which we've been using for code examples, and "theme2" which is another look-and-feel GUI. To switch between themes, all that is required is to load the "setup.xml" file into a text editor and change the theme value attribute from "basic" to "theme2". Your XML would look like this:

FIGURE 7 - Modified Setup XML

Next time you run the application, the shell would use the layout and graphics described in the "theme2" folder.

Once we load our setup XML, we can tell the engine to load and process the GUI XML, which in turn, tells the engine to load and process the content XML. In our code, we have allowed time between loading stages for XML to process, and for graphics to load. We certainly don't want to start trying to show content before we've even loaded the button graphics.

Now that we've loaded and processed the setup XML, the content XML, and the GUI XML, and have shown the first content item, the system just sits and waits for user interaction. From here on out, our application is entirely event driven. When a user presses a button, our button handler calls the appropriate function and goes back to waiting for the next user event. Content flash movies function independently of our shell application, so lengthy presentation, quizzes, or even streaming videos can all be interacted with without concern requiring any knowledge of the shell, and vice-versa.

FROM HERE

Again, this application is by no means the be-all-end-all presentation engine. We've only begun to scratch the surface. Nevertheless, I hope that this project has shown how XML can be used in interesting and unique ways, and has sparked an interest in you to take this concept to another level. Perhaps, at the very least, the included code can be used as a reference to implementing a lot of the new functionality inherent in Flash MX – dynamic text fields, dynamic text formats, class creation, and of course, XML. Good luck, and have fun!

 

Source: g. wygonik

License: Creative Commons