You are Here:Home>>Old Posts>>Exploring a unified component workflow between Flex and Flash

Exploring a unified component workflow between Flex and Flash

Carlos Pinho
By | 2008-02-21T13:38:17+00:00 Feb 21, 2008|Old Posts|

Building applications in Adobe Flash that can also be used as Adobe Flex components can be a challenge, as I learned with a project involving an embeddable video player. Learn from this example how to create a project enabling you to share code across three versions of this player published as a stand-alone Flash application, a Flash-generated Flex component, and an editable Flash CS3 Professional component.
This all started a few months ago. At Almer/Blank we do a lot of work with Flash video. I soon got tired of building new Flash video players for our clients that included more or less the same functionality as all the others—albeit perhaps in a somewhat different design.

So I decided to build a lightweight, easily skinnable Flash video player that we would utilize for a wide variety of projects. We chose Flash primarily because of the size of the Flex framework. Many of our video players are utilized as embeddable players—the same type of YouTube-style player that you see embedded everywhere around the web (see Figure 1).

Flash video player for this project

Figure 1. Flash video player for this project

The primary virtue of these embeddable video players is file size: they must load quickly and not weigh down the pages in which they exist. We had built a video player similar to this one in Flex and it weighed 300K—even without any custom fonts. The video player I built in Flash ended up only around 40K.

However, the first site into which this player was to be implemented was—like most of the work we at Almer/Blank produce—built in Flex. So, right off the bat, unless I wanted to build two video players, I needed to export this Flash video player as a Flex component.

Finally, another client wanted a shared video player for their video site that they could customize. Although I wanted to let them have it, I didn’t want to release any source code. That’s when I learned how to author FLA-editable components for Flash CS3.

In short, I had to build one single application that I could publish three different ways:

  • As a Flash application
  • As a Flash-generated Flex component
  • As an editable Flash CS3 component

Either I was going to figure out a new workflow or I was going to be duplicating a lot of work! I decided to bite the bullet and figure out the workflow.

Planning your Flash application for any of these three items isn’t that much of a challenge; but building an architecture and workflow that enabled me to export all three from the same project brought some nasty little quirks and surprises. This article is about these lessons. Before I get into this workflow, however it’s worth taking a few moments to review just what these components are.

Requirements

In order to make the most of this article, you need the following software and files:

Flash CS3 Professional

Flex Builder 2.01 (includes free Flex 2.01 SDK)

Note: To test the Flex component, you must download the Flex 3 beta from Adobe Labs.

Flex Component Kit for Flash CS3 Professional

Prerequisite knowledge

You should have a good understanding of developing Flash applications and components, as well as Flash video.

Examining the Flash components

A lot of people know at least something about Flash components—they’re the things that help make developing certain features and interactions much simpler. Need a drop-down list? Add a ComboBox component. Need to play some video? Add an FLVPlayback component. Need to display closed captioning with that video? Add an FLVPlaybackCaptioning component. All of the components that come with Flash CS3, and any custom ones you install, are visible in the Components panel (Window > Components), as shown in Figure 2.

Components panel

Figure 2. Components panel

The landscape of Flash components is much richer than many people appreciate—and continues to mature at a rapid pace. It’s not your grand-daddy’s SmartClip, that’s for sure. This article focuses specifically on two aspects of Flash components: the editable components and the Flash-authored Flex components.

Before I continue, it’s worth highlighting that there is much more to components than what I cover here:

  • You can generate components from Flash as MXP files that can be installed through the Adobe Extensions Manager
  • You can create specialized Flex components in Flash that are designed to skin native Flex components, like buttons
  • You can add a Live Preview to your Flash component so it can render on the Stage in the authoring tool as it does in Adobe Flash Player
  • You can skin the Flash components much more powerfully than simply editing them through the FLA

And I haven’t even mentioned styling. In short, there’s much, much more that you can do with components.

The two specific features of Flash components that this article discusses are both new additions to Flash CS3. In my opinion, they both add key value to overall Flash platform development. The first feature, editable v3 components, finally make it possible to have a clean workflow between developers and designers by enabling the distribution of editable visual assets along with compiled code. The second feature is the Flex Component Kit for Flash CS3 Professional, which makes it much easier to generate components in Flash—the tool that has much more visual power and a wider suite of tools for designers to build experiences—that will work cleanly in the Flex framework and your Flex Builder projects.

Flash CS3 v3 components

With Flash CS3 Professional and ActionScript 3.0, Adobe completely overhauled the preinstalled components. This means that the new v3 components are smaller, more efficient, and more powerful—and there are more of them.

But wait, there’s more! One of the most challenging tasks associated with using components has always been customizing the visual assets—for example, having a designer skin them with custom graphics. It’s always been possible, but it’s also been difficult. With most of the v3 components, all you have to do is double-click the component instance to see a nicely organized layout of all graphical elements used by the component (see Figure 3). Just change what you want to change. I call these “FLA-editable components” in this article.

Visual assets for the UIScrollBar component

Figure 3. Visual assets for the UIScrollBar component

As with earlier versions of Flash, it is possible to create your own components. However, in Flash CS3, you can also make your components FLA-editable, just like the ones that come preinstalled. This is a tremendous improvement over the workflow that was possible with previous versions of Flash components. You can code up anything you want, turn it into a component with the compiled code for easy distribution, and still have all the assets completely editable. It’s amazing.

Flash components for Flex

In the time between the release of Flash 8 and Flash CS3, Flex 2 was released. Flex 2, which is also based on ActionScript 3.0, is a framework that makes it much easier to build Flash applications. Like Flash, Flex exports SWF files that play in Flash Player. Unlike Flash, Flex facilitates the application development workflow primarily through the use of components. In essence, everything in Flex is a component.

Unfortunately, a Flex component is not the same as a Flash component. The Flex framework uses a series of classes that are effectively incompatible with Flash SWF files. What if you wanted to build certain assets more complex than a single skin for a Flex application in Flash?

The Flex Component Kit for Flash CS3 Professional comes to the rescue. This kit includes an extension for Flash CS3 that enables you to build components for Flex. In essence, you can convert any piece of code that runs in Flash into a component that is usable by Flex.

Creating the Flash application

I should preface this description by explaining that this workflow is the result of what I learned by doing this project. Without having a nifty article like this one at my disposal, I did not know exactly how to begin the project. I began with what I assumed was the first step: getting the application to work in Flash as a stand-alone Flash SWF file. And that’s exactly what I did. I spent a couple of days working on the code and integrating my designer’s assets. I’ll call this Version 1.

At the end of Version 1, I had a Flash application with all my symbols. The app had a document class called Player and each MovieClip symbol in the library was linked to a class file (for example, the progress bar movie clip was linked to a ProgressBar class file). Because of how I’ve come to work with Flash since the addition of ActionScript 3.0, the Stage and Timeline were completely empty—the Player document class instantiated all display objects through code. Instantiating all visual elements gave me a lot of flexibility.

Because this player had to be flexible, I wanted the discretion of adding and removing visual elements at runtime. For example, if the player receives an XML playlist without a <title> node, I do not need to attach the title bar—which means that the video display window has more room to expand. If the playlist XML has no <link> node, I do not need to add a link button—which means the other controls in the control bar can be positioned differently. In short, instantiating all visual elements through code, rather than directly on the Timeline, gave me a lot more control over the rendering and performance of the video player. My player looked something like Figure 4.

Initial Flash video player

Figure 4. Initial Flash video player

The specific code I used is irrelevant to this topic—since the goal is to build a workflow that works for any Flash CS3 application. However, the basic structure of my app does matter a fair bit, as you’ll see next.

Building the video player to work as a regular Flash application was just the first step. I proceeded next by making the project publishable as a Flex component. I’d already authored Flex components in Flash, and the process was pretty familiar.

Building the Flex component

I got started on version 2 of the project: publishing a Flex component from Flash. I duplicated the project folder and got started converting the video player app. The process for creating a Flex component in Flash is actually pretty straightforward, and certainly well documented. In fact, when you download the Flex Component Kit for Flash, there is a 21-page PDF file that includes step-by-step explanations and walkthroughs.

The first step is to install the Flex Component Kit for Flash CS3 Professional, if you haven’t already. You can download the kit from Adobe Labs.

The download includes an MXP file, which you can install through the Adobe Extension Manager. Launch the Adobe Extension Manager (which you should have if you already have Flash CS3 installed). Click Install and then navigate to and select the MXP you just downloaded. Click Accept on the disclaimer/agreement. When you are done, your Extension Manager window should look something like Figure 5.

Adobe Extension Manager with Flex Component Kit for Flash CS3 installed

Figure 5. Adobe Extension Manager with Flex Component Kit for Flash CS3 installed

Make sure the new Flex component is checked. If Flash CS3 is open, restart it. Now Flash CS3 is ready to start creating Flex components.

Lesson 1: Lose the document class

My first problem appeared immediately: I’d built my Flash stand-alone version using a Document class. This meant that the main class file for my video player was attached to my main Timeline. But authoring any component in Flash requires a symbol in the Flash document library, and the main Timeline is not in the library. So I created a new MovieClip symbol in my library called Player, removed the document class linkage on the FLA file (so the main Timeline no longer had a class file association), linked the new Player movie clip to the Player class, and made the appropriate changes to the Player.as file. The Player movie clip in my library was actually empty, as the Stage was in Version 1; it just linked to the Player class, which controlled and instantiated all objects as needed. Figures 6 and 7 show the structure before and after this process.

Original association between Player.as and Player.fla

Figure 6. Original association between Player.as and Player.fla

Revised association, with Player.fla linked to a new Player movie clip

Figure 7. Revised association, with Player.fla linked to a new Player movie clip

Lesson 2: Don’t link the main MovieClip symbol to a custom class

Now my second problem popped up. I successfully converted my player to run from a movie clip in the library rather than the document itself. However, this required linking the Player MovieClip to my Player.as. What’s wrong with that? Well, for Flash to convert a movie clip into a Flex component, there must be a linkage ID assigned to the movie clip that will serve as the component name in Flex. When I tried linking that movie clip to a custom class file in Flash, I experienced no end of problems. In short, I couldn’t figure out how to do it; I couldn’t successfully have the linkage ID for the movie clip both link to a custom class and serve as the component identifier in Flex. It didn’t crash or cause an error to appear—it just kept failing in new and imaginative ways.

So I created a new movie clip in my library called MediaPlayerFlexComponent. Then I inserted some code on frame 1 of the timeline of this new movie clip that instantiated and initiated the video player. Simplified somewhat for the purposes of this article, this code looked like the following:

import com.almerblank.ABMP.Player;

var player:Player = new Player();

addChild(player);

Yes, code on the timeline! Sorry. If it it makes you feel any better, what I ended up doing was taking that code, pasting it into an AS file (just an ActionScript file, not a class file) and then including that with the following line:

include "../com/almerblank/ABMP/shell/ABMP_flx.as";

In this way, I could still manage the timeline code from the project package, ABMP.

To finish this process off, I needed to establish the proper linkage for my new MediaPlayerFlexComponent. To do this, right-click the symbol in your library and select Linkage.

Ensure that Export for ActionScript and Export in First Frame are checked. Next to Class, enter the name by which you want to refer to this component in Flex (see Figure 8). In this case, I used MediaPlayerFlexComponent. I left Base Class unchanged from the default flash.display.MovieClip setting.

Setting linkage properties for the MediaPlayerFlexComponent MovieClip

Figure 8. Setting linkage properties for the MediaPlayerFlexComponent MovieClip

Now the structure of the app looked like Figure 9.

Video player app after creating and linking the MediaPlayerFlexComponent

Figure 9. Video player app after creating and linking the MediaPlayerFlexComponent

Exporting the Flex component

Now I could finally export the Flex component from Flash. To do this, select the MediaPlayerFlexComponent MovieClip in the library and then select Commands > Make Flex Component.

If your FLA frame rate is not set, the default Flex frame rate of 24 fps applies (which it wouldn’t be if you left it at the default Flash frame rate of 12 fps). You will now see a dialog box prompting you to approve the change to 24 fps. If you do see this dialog box, click OK. Fortunately this will have little effect on the component because all code and object instances occur on a single frame.

The first time you compile this component, in the Flash Output panel, you should see a messaging similar to this:

Command made the following changes to the FLA:

   Turned on Permit Debugging

   Turned on Export SWC

   Set frame rate to 24

   Imported UIMovieClip component to library

Component "MediaPlayerFlexComponent" is ready to be used in Flex.

As you can see from line 5, an instance of the UIMovieClip component has been added to your FLA library. And if you check the linkage of MediaPlayerFlexComponent, you will see that the base class has been automatically updated to mx.flash.UIMovieClip (see Figure 10).

For more information on the UIMovieClip, check the UIMovieClip entry in the Flex 3 Language Reference.

Updated linkage properties for MediaPlayerFlexComponent

Figure 10. Updated linkage properties for MediaPlayerFlexComponent

From now on, when you want to update this component, all you have to do is generate the SWF file by selecting File > Publish or Control > Test Movie.

In whatever folder you have set as the destination for your published SWF file, you will now see a SWC file of the same name as the SWF file. That SWC file is your Flex component.

Ready to test in Flex

To start testing this component, open up Flex Builder and create a new project. Now add your new SWC file to the project library paths. Select Project > Properties. In the left column, select Flex Build Path. In the right panel, select the Library path tab (see Figure 11).

Adding your SWC file to the project library paths

Figure 11. Adding your SWC file to the project library paths

On this panel, click Add SWC, click Browse to navigate to the SWC file you just created, and then click OK. Once you do, your library paths should be updated. Click OK.

Hint: When testing this component, I was constantly updating the SWC file from Flash. Each time you update the SWC component, you need to update the SWC file that your Flex project library paths point to. I discovered that Flex will update the SWC file if you return to your library paths, select the SWC component, click Edit, click OK without changing anything, and then click OK once more to update the library paths. You don’t have to remove and re-add the SWC file each time.

In your application MXML, you must specify the namespace your new SWC component uses. The default (which is what your SWC uses unless you override it) is global, or *. So, in the Application tag, add something like:

      xmlns:myswc="*"

Now, when you start a tag like this:

      <myswc:

you should see some code hinting from Flex Builder indicating that it knows your new component (see Figure 12).

Flex Builder hinting based on your namespace

Figure 12. Flex Builder hinting based on your namespace

That’s great. It works! Or, if your component looks a bit more like mine did at this stage, it doesn’t. Which brings me to the next set of challenges.

Lesson 3: Let’s get physical

In order for Flex to handle your component properly, there must be something physical on the timeline of the movie clip from which the SWC is generated. As I explained, in this version I instantiated everything from the Player class, so there was nothing on the timeline. Which meant it didn’t work.

Of all the challenges that popped up, this was the most easily surmountable. I returned to Flash, edited the MediaPlayerFlexComponent MovieClip, drew a rectangle on the Stage, and gave it a fill with 0% alpha (so it was effectively invisible). I then republished my app (updating the SWC file), updated the library paths in my Flex project, and retested.

Voilà, it worked! Figure 13 shows the app structure after learning that lesson.

Video player structure after adding a graphic to the Stage

Figure 13. Video player structure after adding a graphic to the Stage

Lesson 4: Scale control

One feature of this video player is the ability to render dynamically for different sizes. The player, which is designed at about 400 × 400 (I’m using round numbers instead of the actual dimensions, for simplified math), doesn’t simply scale, it makes more intelligent choices on how to accommodate runtime dimensions that are different than those of the initial design. For example, the control bar is always 24 pixels tall, no matter how tall the player is.

In order to test this feature in Flex, I modified the width and height values of the MXML tag:

<myswc:MediaPlayerFlexComponent id="MyVideoPlayer"

    width="200" height="200"/>

When I tested the component with these settings, I discovered an odd behavior of altering the widths and heights of these components. Instead of rendering at 200 × 200 pixels with the proper layout adjustments I’d accounted for in the code, the player rendered at 100 × 100 pixels—and just scaled down, with none of the layout indications my code should have handled.

It took me a little bit of playing around to figure out what was going on. When instantiating your component, Flex compares the original size of your component (the width and height of the graphic we placed on the Stage, which in our case is 400 × 400) to the size of the instantiated component (here, 200 × 200) and concludes that the scaleX and scaleY are 50% (200 / 400). So Flex renders the component instance at 200 × 200 but also applies a scale transformation, so the component instance actually appears at 100 × 100 (50% of 200 × 200).

In the end, all I did to remedy this situation was apply these two lines of code to my ABMP_flx.as ActionScript file, which is included on frame 1 of the MediaPlayerFlexComponent MovieClip inside of Flash:

scaleX = 1;

scaleY = 1;

This forces the component instance to render at 100% of its scale. Voilà! It all worked. At this point, my video player looked something more like Figure 14.

Video player now adjusted for scale

Figure 14. Video player now adjusted for scale

Moving on

So now I had two separate, but very similar, code bases to produce the same application in two different ways—as a Flash SWF file and as a Flex component. As my next step, I wanted to get the code to work to produce a FLA-editable Flash component.

Building the FLA-editable Flash component

I found this part of the project pretty exciting. I knew that Flash CS3 components could be editable on the Timeline because I’d used a few of the ones that come preinstalled with Flash. But when I started searching for documentation on how to do it, I was quickly frustrated. There is very little information available on how to create Flash CS3 editable components, and it involves a mystical object known only by the somewhat ambiguous name of “ComponentShim.”

Fortunately, I stumbled upon Spender’s post on FlashBrighton, Creating FLA-based components in Flash CS3. That tutorial taught me the basic process of utilizing the component shim, so I started trying to convert my video player into an editable component.

Step 1: Add UIComponent to class paths

Your component will have to extend the UIComponent class. In order for your project to extend that class, you must add that class path to your document settings. Select File > Publish Settings, click the Flash tab, and with ActionScript 3.0 selected in the ActionScript Version drop-down, click Settings. This opens the ActionScript 3.0 Settings dialog box (see Figure 15).

ActionScript 3.0 settings

Figure 15. ActionScript 3.0 settings

Click the “+” button to add a new class path and insert the following:

$(AppConfig)/Component Source/ActionScript 3.0/User Interface

For more information on the UIComponent, see the Class UIComponent entry in the Flex 3 Language Reference.

Step 2: Extend UIComponent

I needed a class that extended the UIComponent, so I created a new class called ABMP_flc.as:

package com.almerblank.ABMP.shell {

   import fl.core.UIComponent;

   import flash.display.*;

   import com.almerblank.ABMP.*;

   import com.almerblank.fl.utils.events.*;

   public class ABMP_flc extends UIComponent {

      public function ABMP_flc(){

      }

      private var _player:Player;

      protected override function draw():void

      {

         init();

      }

      protected function getSkinName():String

      {

         return "ABMediaPlayerFlashComponentSkin";

      }

      private function init():void

      {

         _player = new Player();

         addChild(_player);

      }

   }

}

Step 3: Build an avatar

Create a new movie clip in your library called Avatar. On frame 1, draw a rectangle with x = 0 and y = 0. Make the height and width whatever you want to be the default for the component. The rectangle should have a hairline stroke (for scaling) and no fill.

Step 4: Link a movie clip to the class that extends UIComponent

Add a new movie clip to the library. I called mine ABMP_flc. Now link it to the class you wrote earlier in Step 2. Right-click the movie clip in the library, check the Export for ActionScript and Export in First Frame check boxes. For Class, enter the path to the class you wrote. Leave Base Class as flash.display.MovieClip. I’ll call this the component MovieClip.

Edit this new component MovieClip. On frame 1, add an instance of the Avatar MovieClip at 0,0. As I learned from Spender’s post, UIComponent uses this instance to set its default width and height, and then removes it from the display list immediately. It does this only for the DisplayObject at index 0, so you don’t want any other display objects on this frame.

Step 5: Make the designer’s life easy

Once you complete this component and someone uses it in a Flash app, all of the library assets from your component will be added to that FLA file. These are the assets that your designer needs to update and redesign the app. Instead of forcing your designer to hunt around the library to find all the movie clips and graphics that you use and update them one at a time, create a guide that facilitates this process.

If you read Spender’s post, you’ll see how you can do this using a dedicated skins MovieClip for this purpose. However, I found it easier simply to place a guide layer on frame 1 of the component MovieClip and include all the component assets in that guide (see Figure 16).

Guide layer for all the component's assets

Figure 16. Guide layer for all the component’s assets

To do it this way, insert a new layer in the component MovieClip, right-click the layer, and select Guide. Drag all the assets you want to the layer. Layout and positioning and parent-child hierarchies do not matter. Since this is a guide layer, it will not be included in what is published from Flash.

Step 6: Create a component definition

Right-click the MovieClip component in your library and select Component Definition. Next to Class, assign a class name for this component and click OK.

Now I show you how to handle the final step of preparing an editable Flash CS3 component: using the component shim.

Distributing the Flash component

When you distribute this component, you distribute a FLA file. It contains all the library symbols of this component, which is how the visual assets are distributed.

But you probably don’t want to distribute the code along with the component FLA. This is where the ComponentShim symbol comes in. In effect, ComponentShim enables you to compile all your code into your FLA library, so that when you distribute the component FLA library, you can distribute the compiled code and not have to include your class files.

Create a MovieClip component to be the shim

Create a movie clip in your library and give it some meaningful name, like Shim. To make it easy to find it on the Stage later, include some shape on frame 1 of Shim. Then right-click Shim in the library and select Linkage. Check the Export for ActionScript and Export in First Frame check boxes and assign a name to the class, such as Shim (the class name is arbitrary; just ensure that it does not conflict with any real classes). Click OK to register the changes.

Next, right-click Shim in the library and select Convert to Compiled Clip. If your classes compile properly, you will see a symbol in your library with the component icon (as opposed to the MovieClip icon) with a name like “Shim SWF” (it will append “SWF” to whatever the name of the source movie clip is).

Here is where you may think you’ve run into a major problem. (I know I did.) The Shim SWF component must be added to each movie clip in your library that links to a real class. For each such movie clip in your library, you must add Shim SWF to frame 2 of the movie clip. Because I had over 30 movie clips in my library that linked to real classes, that meant I had to add the Shim SWF to 30 separate movie clips. And because I had to recompile the Shim SWF each time I updated my code, this meant I would have to do this each time I wanted to update the component.

Seeing as the whole purpose of this exercise was to build an efficient workflow, this was a game-stopper to me. I couldn’t spend 20 minutes to update the Shim SWF instances throughout my app each time I wanted to test an update.

This led to the final major architectural adjustment in my video player: the shift from inheritance to encapsulation.

Encapsulate, don’t extend

Flash is an incredibly visual environment. In most projects—including the code-heavy ones—controlling visual elements with code is essential. This means your code, which resides in class files, must be able to control symbols from the FLA file, either directly from the library or on the Stage. There are two basic ways of doing this: encapsulation and inheritance.

Encapsulation means that your class has a pointer to a movie clip, so the code can control the movie clip by talking to the pointer. Inheritance means that your class is a movie clip, so it can control the movie clip by controlling itself.

Here are two very simple classes that attempt to illustrate that point—both would set the alpha of a movie clip to 50%:

Encapsulation sample

package

{

      import flash.display.MovieClip;

      public class EncapsulationSample

      {

         public var mc:MovieClip;

            function EncapsulationSample()

            {

            mc = new MovieClip();

            mc.alpha = .5;

            }

      }

}

Inheritance sample

package

{

      import flash.display.MovieClip;

      public class InheritanceSample extends MovieClip

      {

            function InheritanceSample()

            {

                  alpha = .5;

            }

      }

}

If I wanted to instantiate each of these from the Stage and add the generated movie clip to the Stage, the code for both cases would look like the following:

var encap:EncapsulationSample = new EncapsulationSample();

addChild(encap.mc);

var inherit:InteritanceSample = new InteritanceSample();

addChild(inherit);

Back in the ancient, mystical world of ActionScript 2.0, I was never really that comfortable with movie clip inheritance. In most cases, I opted for encapsulating my movie clips rather than extending them. With the ease and flow of ActionScript 3.0, however, I’ve utilized inheritance much more frequently. Hence my problem. As I explained when I described Version 1 of the video player, I used inheritance for dozens of classes, linking the movie clips in my FLA library to custom class files that extended the movie clip and defining the behavior for those assets (such as mute button, progress bar, title bar, and so on). Unfortunately, this is not a wise path when it comes to creating components.

So, as one of dozens of similar examples in my source, I have a TitleBar in my video player. Up until this point in development, I had a TitleBar MovieClip in my library that linked to a TitleBar.as class file. That TitleBar class file extended MovieClip and then included all the other code that I needed to run my TitleBar. But when publishing as a FLA-editable Flash component, this meant I would have to update the Shim SWF in the TitleBar.

To ensure that I would have to update only the Shim SWF in one location throughout my component, I went through and changed all the code to utilize encapsulation instead of inheritance. Returning to my TitleBar example, this meant that the TitleBar MovieClip in my library now linked to a nonexistent class, TitleBarMC. My TitleBar.as class no longer extended MovieClip but instead now included a property called mc, which was an instance of the TitleBarMC MovieClip. So my TitleBar class could still effectively control my TitleBarMC MovieClip but I would not have to update the Shim SWF in the TitleBar at all.

At the end of this refactoring process, the only movie clip in my library that required the Shim SWF was the main component MovieClip, ABMP_flc, which you built in Step 2. Figures 17 and 18 illustrate the changes. The resulting source looked something like Figure 19.

Before, with inheritance

Figure 17. Before, with inheritance

After, with encapsulation

Figure 18. After, with encapsulation

Video player refactored for encapsulation

Figure 19. Video player refactored for encapsulation

Moving on

I finally had my video player working all three ways: as a Flash SWF, as a Flex component, and as an editable Flash component. However, I had accumulated three separate code bases along the way to make it happen. The whole point when I started was to get the project to where I had only one code base to maintain and update.

So now I just had to make that happen.

Creating the single code base

I certainly learned some peculiar behaviors in order to make the vast majority of my code directly reusable among these three different projects. Being stuck with three copies of virtually the same code and assets was not tenable. Each time I wanted to fix a bug or add a new feature, I would have to make three identical source updates. My goal now was to combine all my source so that I could maintain one code base but still publish all three versions of the project.

As much as the efficiency expert in me wanted to consolidate all of this into a single FLA file, that is not possible. No matter how successful I would be, I knew I would need separate FLA files for the three various versions of this project. Here’s why:

  • Each component that is added into your FLA file, set to export for ActionScript on the first frame, increases the file size of your generated SWF file. When I exported the plain-vanilla Flash SWF version of this video player, it was 40K (including graphics and fonts—not bad!). As soon as I added UIMovieClip into my library (which I had to do to create the Flex component version of the video player), the file size boosted to 76K. That’s an extra 36K that I do not need or want in the plain Flash version of the project. But unless I wanted to constantly remove and re-add the UIMovieClip to my library during a publish process (and the goal of this process was to develop an efficient workflow, not to consolidate source FLAs into one), I had to separate the FLAs.
  • The file format for an editable Flash component is FLA, which means when someone uses your component, all the various symbols from the component library are added into the user’s document library. There is no need for the Flash component to have the UIMovieClip, for example, or any FLA-specific assets.

I knew I needed at least three FLA files that shared most assets, but also had some unique assets. In essence, each of the three FLA files would follow the model in Figure 20.

Model for sharing code and assets in each version of the player

Figure 20. Model for sharing code and assets in each version of the player

When implemented project-wide, the project source would look something like Figure 21.

Sharing source and assets across all FLA files

Figure 21. Sharing source and assets across all FLA files

Sharing code was actually the easy part. All versions of the project used the same packages and classes, so I just needed to point each FLA file to the same com folder. I was willing to maintain a single, unique AS file for each FLA file—all other code had to be shared cleanly between all versions.

To share the assets, I used a feature of Flash called shared libraries. These aren’t the same as runtime shared libraries, or RSLs. When your Flash project uses RSLs, the SWF file loads assets from another SWF file at runtime while playing in Flash Player. Instead, I’m sharing the assets at author-time, in the Flash authoring tool.

It’s actually a really simple process. Open one FLA file with your assets (FLA A) and then open another FLA file (FLA B). For the sake of relative linking and easy updating over time, it’s smart to place both of these FLA files in the same folder. Open a second library panel (click the New Library Panel button in the upper left of your library). Make sure one library panel is tied to FLA A and the other to FLA B. Then simply drag the symbols from the library of FLA A into the library of FLA B.

Wait, you ask: Didn’t I just copy and paste? No, not really. It is true that the effect is the same as copying the assets from one FLA library and pasting them into the other library. But the assets are now linked. This means that you can right-click the imported assets in FLA B (either one at a time or many at once) and select Update to bring up an Update Library Items dialog box (see Figure 22).

Update Library Items dialog box

Figure 22. Update Library Items dialog box

On the left you will see the list of the symbols that have linkages to other FLA files. Text at the bottom of the dialog box tells you how many of the selected symbols need to be updated (if FLA A has been updated since these symbols in FLA B were last updated). Check all that you want to update and click Update.

A word of experience: Updating symbols from linked libraries can frequently fail for no good reason, in which case the Update Library Items dialog box looks something like Figure 23.

Update failure of shared library symbols

Figure 23. Update failure of shared library symbols

Many times, Flash tells you that the update failed, when it actually worked properly. Here’s another weird one: sometimes when linking symbols from a FLA file as a shared symbol, I lose the ability to save my shared asset library. The only way out of that is to quit and restart Flash. Lesson learned: save, save and save some more.

Doing it

So I created four FLA files. The first, which I call ABMP_SharedAssetLibrary.fla, contains all my symbols, including movie clips (with linkages), graphics, and bitmaps. Then I have three more—one for each version of the project I want to export (Flash app, Flex component, and Flash component). Each of the production FLA files has all the assets from the assets FLA file in a folder called ABMP_assets, and a separate folder called My_assets with any symbols unique to that FLA.

When writing the code utilized for each FLA file, I ensured that all code specific to a FLA would be located in a single AS file. So in addition to all the classes shared by all three production FLA files, I built three AS files, one for each production FLA file. I placed these AS files inside a shell package in the project package.

Flash stand-alone

FLA: ABMP_fla.fla

AS: com.almerblank.ABMP.shell.ABMP_fla.as extends flash.display.MovieClip

FLA library: The ABMP_fla.fla has a movie clip called ABMP_fla that is linked to ABMP_fla.as, which contains the information for instantiating the Player inside of a Flash movie (see Figures 24 and 25).

ABMP_fla.fla library

Figure 24. ABMP_fla.fla library

Overview of the ABMP_fla.fla structure

Figure 25. Overview of the ABMP_fla.fla structure

Flex component

FLA: ABMP_flx.fla

AS: com.almerblank.ABMP.shell.ABMP_flx.as raw ActionScript included from timeline in the FLA

Library: ABMP_flx.fla has a movie clip called MediaPlayerFlexComponent in the library, which uses mx.flash.UIMovieClip as the base class. The library for ABMP_flx.fla also contains the UIMovieClip component (see Figures 26 and 27).

ABMP_flc.fla library

Figure 26. ABMP_flc.fla library

Overview of the ABMP_flc.fla structure

Figure 27. Overview of the ABMP_flc.fla structure

Flash component

FLA: ABMP_flc.fla

AS: com.almerblank.ABMP.shell.ABMP_flc.as extends fl.core.UIComponent

Library: ABMP_flc.fla has a compiled component called ABMP_flc, which is linked to the ABMP_flc.as class and which also contains an instance of the Avatar MovieClip (on frame 1) and an instance of the Shim SWF (on frame 2). I’ve also included a guide layer on frame 1 with all the visual assets to help the designer when he or she wants to customize the editable Flash component (see Figures 28 and 29).

ABMP_flx.fla library

Figure 28. ABMP_flx.fla library

Overview of the ABMP_flx.fla structure

Figure 29. Overview of the ABMP_flx.fla structure

Done

In the end, the project looked something like Figure 30.

Final project (click to enlarge)

Figure 30. Final project (click to enlarge)

Where to go from here

As you can see, I spent a fair bit of time re-engineering my player to ensure the architecture could perform as required when published these three different ways. Because I was constrained by the behaviors and restrictions of each of my three desired output formats, my code is structured quite differently than it would have been had I wanted only to produce a single version (just a Flash application or just a Flash component or just a Flex component, rather than all three). Because of the need to publish as components, I couldn’t really use the Document class. Because of the mysterious ComponentShim (and my desire to minimize how much work goes into each publication), I used encapsulation instead of inheritance for all library assets. And so on.

The upshot is that more than 95% of the code and assets are directly shared across the entire project. For each of the three versions I needed to produce, I in effect created a shell FLA file for that version, including the few lines of code and asset or two required to instantiate my player in the different versions. So now when I want to add a new feature, or fix a bug, I need only update the code and assets once. I still need to go through three separate publish actions (one for each of the production FLAs) but that represents a fraction of the effort if I instead needed to replicate my code and asset updates across three otherwise identical code bases.

Some of what I’ve written is well documented, while other information isn’t as readily available. The point of this article is to bring it all together into a single code base and workflow. As the Flash platform continues to mature, the need for more efficient workflows between the various parts of the platform, and between designers and developers, continues to increase.

For more information on many of the topics covered in this article, please visit some of the following links:

In addition, I cover the process of creating Flex components in Flash in two chapters in my recently published book, AdvancED Flex applications: Building Rich Media X (Friends of ED, 2007) .

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License

About the author

R Blank is CTO of Almer/Blank, an Adobe Solution Partner based in Venice, California, that specializes in video and application development for the Flash platform. He is the lead author of AdvancED Flex applications: Building Rich Media X (Friends of ED, 2007) as well as the author/instructor for the JumpStart Flash CS3 training DVD from Magnet Media. R founded and manages LA Flash, a community of over 3000 industry professionals. He also runs the Rich Media Institute, an Adobe Authorized Training Center, and teaches at USC Viterbi School of Engineering. Previously, R co-founded Wildform where he was a co-creator of Flix, the first video encoder for Flash.

About the Author:

Carlos Pinho
A father, a husband and a geek... Carlos was the founder of projects like The Tech Labs and Flash Enabled Blog. He is the founder of TekTuts He is passionate about technologies. Their main skills are in analytics, transport & logistics, business administration. He also writes about programming resources, trends, strategy and web development.