FireworksColdFusionDreamweaverFreehandFlashMXHome
Latest New Content

Latest Free Content
View All
Free Content
Accessibility
CMX Learning Guides
Hosted by enterhost

Flash-Flex Integration - Part 6: Editing Flash Code in Flex Builder

By: Joseph Balderson

Sometimes, when you're coding a Flex application, don't you just wish you could use a Flash animation, right there? And in Flash, don't you sometimes wish you could use that one class in Flex, or that one component, which would make your life so much easier? It is at such times that  developers encounter the limitations of their tools, be it in Flex or in Flash. This series aims to explore the possibilities inherent in an integrated Flash-Flex workflow, bridging the gap between the two technologies, enabling a greater range of development options.

In this article, we will delve into Flash-Flex integration on a more intimate level, using both Flash and Flex in a completely integrated development workflow. Using David Stiller's Click-and-Paint tutorial as a basis for our enhanced application, we will convert a timeline-based Flash project into a class-based project, but using Flex Builder as the code editor. Essentially we will use the Flash IDE as the assets editor and SWF compiler, and Flex Builder as the ActionScript 3 editor (without using the Flex compiler).

In this article, you will learn how to set up a Flex project workspace to enable the editing of Flash IDE-compiled ActionScript 3 class files. In doing so, you will no doubt discover why Flex Builder is a much more powerful tool for ActionScript class editing than the Flash Actions panel. As one of my Flash colleagues is fond of saying, "Once you go Flex, you never go back." :) But this isn't about making converts to either Flash or Flex development. Whatever your specialty, this series is here to show you that with a little ingenuity, you can have your cake and eat it too.


Flash Actions panel or Flex Builder: for code editing, there is no contest.

A Merging of Disciplines

Many Flash developers, when they have reached that point in their experience of the Flash authoring tool, suddenly realize how completely and utterly inadequate the Flash IDE is at code editing. Most of this is due to the fact that the Actions panel in Flash, compared to more mature tools like Eclipse, Visual Studio or even Dreamweaver, is missing some very crucial features. In a word, Flash sucks at code editing.

But that's okay. Flash was never meant to be a coder's paradise. It was meant to be the interactive fusion of art and science, the synthesis of design and code, the right-brain meets left-brain full hemisphere experience-creator's dream. And at that, Flash has done enormously well, bringing together creative ideas and assets from design tools such as Photoshop, Fireworks and Illustrator, even After Effects and various video editing tools, combined with some industrial-strength code from the ActionScript 3.0 language, all backed by an ultra-fast precision-engineered Flash Player runtime. Not bad for what used to be nothing more than a fancy vector-based gif-animator.

Flash does design and animation very well; that's what the timeline is for. But now that ActionScript 3 has come along, it's almost as if part of the technology has outstripped its original tools. I've heard many Flash developers expound: "You don't really use the Actions panel for code, do you?" The Flash IDE is just simply no longer up to the task of managing an advanced OOP, class-oriented coding workflow.

Why then do so many developers choose third-party ActionScript editors such as SEPY, FlashDevelop and FDT, for code editing with the Flash IDE, instead of just switching to being Flex developers? The reason is that many Flash developers love mixing up design with code, even as they use industrial-strength tools for their code editing needs. They like coding with the assistance of a timeline metaphor, and may not always want to build component-centric experiences, no matter how many cool things you can do with the Flex Framework. Others simply have not found the time or opportunity to make the migration to component-centric frameworks meant for RIA-building in the Flex development environment. Whatever the reason, that's okay. Flash developers, you can have your cake and eat it too.

The time has come to introduce the power of Flex Builder into the Flash development workflow.


Image 1: Using Flex Builder in the Flash development workflow.

This tutorial assumes a basic familiarity with installing and using Flex Builder. For a basic Flex Builder primer, see the Community MX tutorial Flex 101: Part 3 - Using Flex Builder 2, most of which is equally applicable to Flex Builder 3.

Preparing the Workflow

In order to begin coding our application, we first need to prepare our workflow.

  1. Open Flex Builder 3.
  2. Switch to the C:\flex_cmx_flashflex\_fx3_workspace workspace that we have been using for this series. If you are using a Macintosh, C: is your home directory for Flex projects.
  3. In Flex Builder, ensure that Project > Build Automatically is unchecked.

    This is a crucial first step. We do this because we are using Flex Builder as an ActionScript editor, not a SWF compiler. By turning off Build Automatically, we are effectively disabling automatic compilation by the Flex compiler. To maintain the 'Flash' part of the workflow, we will be using the Flash IDE to compile the SWF.

  4. Create a New ActionScript Project. Place in the C:\flex_cmx_flashflex\ directory, and name it FlashFlex_06_Fx3_FlashAS3, according to the naming convention we have set up for this series.


    Image 2: Creating an ActionScript Project in Flex Builder 3.

    Creating an ActionScript Project as opposed to a Flex Project allows us to sidestep having to declare an MXML application file for the project, which would serve no purpose, as we cannot use MXML with the Flash compiler.

    Flex-compiled applications do not have a timeline or even frames upon which to lay out assets, which is why MXML files are necessary in Flex. The Design View in Flex Builder allows one to see a graphical representation of the MXML layout, but it is not meant to duplicate the versatility of the Flash timeline. Creating an ActionScript project in Flex forces the developer to rely on dynamic instantiation of assets, without the advantage of MXML as a layout helper.

  5. Click Next. In the next screen, define the Main source folder as src, and the Main application file as com/communitymx/flashflex/Paint.as . Leave the other fields at their defaults.


    Image 3: Creating an ActionScript Project in Flex Builder 3.

  6. Click Finish.

    Notice that Flex Builder automatically creates the necessary package folders for the Paint class, and auto-fills the basic class code to start off our application, and opens the file in the Editor.

  7. Copy the source files from this tutorial's download into the src folder. Move the Paint_final.as file into the src/com/communitymx/flashflex/ folder.
  8. Open paint_as3.fla in Flash CS3.

    We have borrowed this project from David Stiller's Creating Click-and-Paint Flash Content, Part 2 tutorial, and will be converting it to a class-file based project using Flex Builder.

  9. Save the file as paint_flash-flex.fla .

    This is the Flash sourcefile that we will be working with in this tutorial. Think of the other two FLAs as the "before and after" files.

  10. Go back to Flex Builder. Your Flex Navigator view in Flex Builder should now look like the following:


    Image 4: The project file directory in the Flex Navigator view.

    The files ending in _final are the completed files for this tutorial.

    Now that we have finished setting up our workflow, let us begin converting the application.

Creating The Document Class

  1. In the paint_flash-flex.fla file in Flash CS3, click on a blank area of the stage, and set the Document class to com.communitymx.flashflex.Paint in the Properties panel.

    This points the FLA to use the code in the Paint.as class file instead of the timeline.

  2. In the Actions panel for Frame 1, comment out all the code by placing a start block comment symbol /* at the very start of the code, and an end block comment symbol */ at the very end of the code.
  3. Switching to Flex Builder, in the Paint.as Editor, you should see the following code:
    package com.communitymx.flashflex {
       import flash.display.Sprite;
    	
       public class Paint extends Sprite
       {
          public function Paint()
          {
          }
       }
    }
    
    

    Code 1: The default Paint.as code.

  4. Add the following line to the Paint class constructor. This will allow us to test if the Paint class is being instantiated correctly.
          public function Paint()
          {
             trace("ready to go!");
          }
    

    Code 2: Adding a trace statement to the Paint class constructor.

  5. Go back to Flash, and Test Movie.

    What happens? Errors!


    Image 5: The Flash CS3 Compiler Errors panel.

    Why does this happen? Well, notice that the default class for a Flex ActionScript Project is Sprite. Flex does not use a timeline (it is in fact a "single frame" application), so of course the main class for a Flex ActionScript application would be a Sprite. But the main timeline for an Flash IDE-built SWF is a MovieClip, which is a subclass of Sprite with additional timeline properties and methods. Without access to the properties and methods of the MovieClip class, stage assets are not recognized, and generate compiler errors. So we must convert our Paint class to a subclass of MovieClip, not Sprite.

    And here is where the true power of Flex Builder really shines.

  6. In Flex Builder, in the line "public class Paint extends Sprite," select the word "Sprite", and type the word "Movie". Now, before you complete that word, press Control-Space (or Option-Space for Mac). You should see the following:


    Image 6: The Flex Builder auto code completion popup.

  7. Now either select the word MovieClip in that menu, or simply press Enter if it is already selected. If the popup disappears and you did not manage to select the word, place your cursor after the word 'Movie", press press Control-Space again.

    Not only does Flex Builder present you with a list of classes to complete the word, intelligently selected from the current package scope, but it adds the MovieClip import statement for you, and deletes the now unused Sprite import. For any Flash developer who has slogged through coding in the Actions panel trying to remember the spelling of countless class names (*author raises hand*), this feature alone is a godsend. But read on, there's more.

    If the auto-import or the auto-import-deletion feature does not work, it could be that you have turned off one or both of these capabilities in your Flex Builder preferences. Select Window > Preferences, find the Flex > Editors > ActionScript page, and ensure that "Keep imports organized" and "Remove unused imports when organizing" are checked.

    Your code should now look like the following:

    package com.communitymx.flashflex {
       import flash.display.MovieClip;
    	
       public class Paint extends MovieClip
       {
          public function Paint()
          {
             trace("ready to go!");
          }
       }
    }
    

    Code 3: Paint.as with correct subclassing.

  8. Go back to Flash CS3, and Test Movie.

    You should now see the text "ready to go!" in the Output panel.

    We have now successfully created a class file in Flex Builder, associated it as the Document class for a Flash FLA Document, and compiled it in Flash.

From The Timeline to OOP

Now let's begin the process of converting a timeline-coded project into a class file-coded project.

  1. In the Actions panel for Frame 1 in Flash CS3, uncomment the code.

    We will now begin the process of migrating this code from the Flash timeline to our new class file in Flex Builder.

  2. Cut and paste the ColorTransform import statement into the Paint.as package definition under the MovieClip import.
  3. Comment out the trace statement in the Paint class constructor function.
  4. Move all the code on the timeline that is not a function into the Paint class constructor. Make sure you indent the code properly.

    All the code you should have remaining in the Actions panel are the paintClickHandler, clearAll, drawingClickHandler and setColor functions.

  5. Move all four remaining functions into the Paint class body. Again, be sure you indent your code correctly, and paste it just after the end bracket of the constructor function.
  6. After you have done this, be sure there is no code left on the timeline.

    Your Paint.as file code should now look like the following:

    package com.communitymx.flashflex {
       import flash.display.MovieClip;
       import flash.geom.ColorTransform;
          
       public class Paint extends MovieClip
       {
          public function Paint()
          {
             //trace("ready to go!");
             var col:ColorTransform = new ColorTransform();
             col.color = 0xFFFFFF;
             
             var colorTable:Dictionary = new Dictionary();
             colorTable[paintRed] = 0xFF0000;
             colorTable[paintBlue] = 0x0000FF;
             colorTable[paintYellow] = 0xFFFF00;
             colorTable[paintClear] = 0xFFFFFF;
             
             var paintBuckets:Array = new Array(paintRed, paintBlue,
     paintYellow, paintClear);
             var drawingPieces:Array = new Array(cap, sliceA, sliceB,
     sliceC, sliceD, sliceE, sliceF);
             
             // initialize brush
             Mouse.hide();
             brush.daub.visible = false;
             brush.mouseEnabled = false;
             brush.mouseChildren = false;
             brush.startDrag(true);
             
             // paint code
             for (var i:int = 0; i < paintBuckets.length; i++) {
                paintBuckets[i].addEventListener(MouseEvent.CLICK,
     paintClickHandler);
             }
             paintClearAll.addEventListener(MouseEvent.CLICK,
     clearAll);
    
             // beach ball code
             for (i = 0; i < drawingPieces.length; i++) {
                drawingPieces[i].addEventListener(MouseEvent.CLICK,
     drawingClickHandler);
             }
          }
    
          function paintClickHandler(evt:MouseEvent):void {
             col.color = colorTable[evt.target];
             setColor(brush.daub, col.color);
             brush.daub.visible = true;
             if (col.color == 0xFFFFFF) {
                brush.daub.visible = false;
             }
          }
          function clearAll(evt:MouseEvent):void {
             for (i = 0; i < drawingPieces.length; i++) {
                setColor(drawingPieces[i], 0xFFFFFF);
             }
             setColor(brush.daub, 0xFFFFFF);
             brush.daub.visible = false;
          }
          function drawingClickHandler(evt:MouseEvent):void {
             setColor(MovieClip(evt.target), col.color);
          }
          
          // helper functions
          function setColor(mc:MovieClip, hue:int):void {
             col.color = hue;
             mc.transform.colorTransform = col;
          }
       }
    }
    

    Code 4: The migrated timeline code.

Let us tempt fate and see if that works without any tweaking.

  1. In Flash CS3, compile the SWF with Test Movie.


    Image 7: A missing class reported in the Compiler Errors panel.

    It is evident from the nature of the error that the compiler cannot find the MouseEvent class. So we need to add that import statement to the list. Flex Builder's auto-import completion only works if you use the code completion feature; it does not work for a cut-and-paste. So we must add this in by hand.
  2. Below the last import statement in Paint.as, import the flash.events.MouseEvent class.

    Notice that Flex Builder allows for code completion for packages and classes, much like Flash does.

  3. In Flash CS3, compile the SWF with Test Movie.

    One problem solved, and others appear. But we are getting closer.


    Image 8: More errors in the Compiler Errors panel.

    Take a look at the code, a careful look. Look at the constructor function.

    Look again. What do you see?

    We see properties declared as local variables in the constructor attempting to be accessed by functions outside their scope. Which is why we are getting the "undefined property" errors in the code.

    In addition, we are attempting to instantiate certain classes, such as Dictionary and others, without importing them first. This does not mean that the timeline code was flawed (it compiled, didn't it?) It means that we can get away with a certain amount of "loose importing" when coding on the timeline, but not when we are coding in a class file.

    So all of the 1120 errors in the Compiler Errors panel in Flash CS3 indicate property references for which we are either missing an import statement, or we have declared a scope local to the constructor, which must instead be declared as a class property.

  4. Add the following property declarations at the beginning of the Paint class body before the constructor function:
       public class Paint extends MovieClip
       {
          private var col:ColorTransform;
          private var colorTable:Dictionary;
          private var paintBuckets:Array;
          private var drawingPieces:Array;
          private var i:uint;
    
          public function Paint()
          {
    

    Code 5: Adding property declarations.

    When you type the property declarations, type until you get to the colon, then type part of the class word, such as "private var col:Col". Press Ctrl-Space (or Option-Space) to use the code completion feature to fill in the class name, and you will trigger the auto-import to place import statements for you.

    Notice anything else? Flex builder organizes your import statements alphabetically by package. Neat, huh?

    We also need to change the local variables in the constructor function to class property references.

  5. Change the code in your constructor function to reflect the following:
    public function Paint_final()
    {
       col = new ColorTransform();
       col.color = 0xFFFFFF;
       
       colorTable = new Dictionary();
       colorTable[paintRed] = 0xFF0000;
       colorTable[paintBlue] = 0x0000FF;
       colorTable[paintYellow] = 0xFFFF00;
       colorTable[paintClear] = 0xFFFFFF;
       
       paintBuckets = new Array(paintRed, paintBlue, paintYellow, 
    paintClear);
       drawingPieces = new Array(cap, sliceA, sliceB, sliceC, sliceD, 
    sliceE, sliceF);
       
       // initialize brush
       ...
    

    Code 6: Updating the constructor with class property references.

    In addition, the error messages in the Compiler Errors panel tell us that we also need to import the Mouse class.
  6. Import the flash.ui.Mouse class in the class body after the other import statements.

    Your class file should now have the following code:

    package com.communitymx.flashflex {
    	import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.ui.Mouse;
    import flash.utils.Dictionary; public class Paint extends MovieClip { private var col:ColorTransform;
    private var colorTable:Dictionary;
    private var paintBuckets:Array;
    private var drawingPieces:Array;
    private var i:uint;

    public function Paint() { //trace("ready to go!"); col = new ColorTransform(); col.color = 0xFFFFFF; colorTable = new Dictionary(); colorTable[paintRed] = 0xFF0000; colorTable[paintBlue] = 0x0000FF; colorTable[paintYellow] = 0xFFFF00; colorTable[paintClear] = 0xFFFFFF; paintBuckets = new Array(paintRed, paintBlue, paintYellow, paintClear); drawingPieces = new Array(cap, sliceA, sliceB, sliceC, sliceD, sliceE, sliceF); // initialize brush Mouse.hide(); brush.daub.visible = false; brush.mouseEnabled = false; brush.mouseChildren = false; brush.startDrag(true); // paint code for (var i:int = 0; i < paintBuckets.length; i++) { paintBuckets[i].addEventListener(MouseEvent.CLICK, paintClickHandler); } paintClearAll.addEventListener(MouseEvent.CLICK, clearAll); // beach ball code for (i = 0; i < drawingPieces.length; i++) { drawingPieces[i].addEventListener(MouseEvent.CLICK, drawingClickHandler); } } function paintClickHandler(evt:MouseEvent):void { col.color = colorTable[evt.target]; setColor(brush.daub, col.color); brush.daub.visible = true; if (col.color == 0xFFFFFF) { brush.daub.visible = false; } } function clearAll(evt:MouseEvent):void { for (i = 0; i < drawingPieces.length; i++) { setColor(drawingPieces[i], 0xFFFFFF); } setColor(brush.daub, 0xFFFFFF); brush.daub.visible = false; } function drawingClickHandler(evt:MouseEvent):void { setColor(MovieClip(evt.target), col.color); } // helper functions function setColor(mc:MovieClip, hue:int):void { col.color = hue; mc.transform.colorTransform = col; } } }

    Code 7: The completed code for Paint.as.

    Notice that we have declared the class instance properties with the private class attribute (also known as an "access control modifier"), but we have not done so for any of the functions. Although explicitly assigning class attributes to all properties and methods of a class is a best practice, not doing so merely defaults these class members to internal, which is to say that the class member is accessible to any reference inside the same class package.

  7. Go back to Flash CS3, and Test Movie.

    Eureka! It works! And this time with no errors. You should now be able to use the application as it was originally created in the paint_as3.fla file.

Using the Flash-Flex Builder Workflow

Now that we have created our class file-based application, using Flex Builder as the editor, and Flash CS3 for the compiler, we can really see the distinct advantages of staying with Flash for part of our workflow.

In Flash we have:

And with Flex Builder, we have:

Combine these tools, and we have one extremely powerful workflow.

Another nice feature in Flex Builder, as seen in the preview for this tutorial, is the Outline view. This shows you all the class members within a class, including import statements, giving you a bird's eye view of your class capabilities.

Tip: to fullscreen an Editor in Flex Builder, double click the editor tab.

Tip: if you have a widescreen or large size monitor, open two class files, and grab and drag one of the editor panels till it docks on the right-hand side of the Flex Builder workbench, showing two columns of Editor views, thus allowing you to edit two files at once!

Tip: To check out all the neat features in Flex Builder that are just a shortcut away, try hitting Ctrl-Shift-L (or Option-Shift-L on Mac)...

A Few Important Caveats

There are a few very important caveats one must remember when using Flex Builder to edit ActionScript files for Flash projects:

  1. As previously mentioned, Build Automatically must be turned off. Otherwise the Flex compiler will auto-compile the main "application" class, and most likely generate errors in Flex Builder. This alone will not prevent you from using Flex Builder as an Editor, but it can be very confusing and annoying.
  2. The bin-debug, libs (if present) and html-template folders are for Flex-compiled projects only. If you are using Flex Builder for editing Flash-compiled ActionScript files, ignore them.
  3. The Problems view, the Debugger and the Profiler in Flex builder are for Flex projects only. If you are not using the Flex compiler, these views will be of no use. In using Flex Builder solely as an ActionScript editor with the Flash compiler, please use the Output panel and the Compiler Errors panel in Flash CS3 for all debugging purposes.
  4. The code completion and auto-import features of Flex Builder employ the Flex compiler for its 'intelligence". When completing import statements or other package assist completion, any package starting with "mx" is part of the Flex Framework, and will not be accessible by the Flash compiler, so you will get compiler errors if you attempt to use a class reference that is in within the Flex SDK.
  5. For this reason, any Flash CS3 components in the fl.* package will not be visible to the code completion or auto-import features.
  6. You cannot use the Flex Compiler to render a Flash CS3 SWF, no matter how creative you get with importing Flash SWC files. The Flash Compiler has a unique relationship with the Flash authoring environment that the Flex compiler cannot duplicate at this time.
  7. MXML files and Metadata tags are meant solely for the Flex projects involving the Flex compiler. Which is why there is no purpose in using a Flex Project in Flex Builder for a Flash-compiled application, as indicated early in this tutorial.
  8. Flex Builder cannot trigger the Flash IDE to compile a SWF without some serious coding voodoo way beyond the scope of this tutorial. Unless you're an advanced developer, switching back to Flash and pressing Ctrl-Enter is way less trouble.

Taking it From Here

Now you have enough know-how to use this workflow in your own projects. There are so many more cool features in Flex Builder that make one's coding experience efficient, that they are too numerous to list them all here. You can find out the rest on your own, with a good Flex Builder tutorial or by picking up a few "power tips" on Flex Builder.

In closing, I hope this tutorial convinces you that Flex Builder is not just for Flex, it can be for coding Flash projects as well.

Happy coding!


Keywords
Flash CS3, Flex, integration, workflow, flash-flex, flex-flash, fla, swf, compiler, Flex Builder