Using Flex with Haxe

This is a rough introduction to getting the Flex 2 framework and Haxe to work together. It shows one possible way to develop a Flex applications based on Flash Player 9 that includes code written in Haxe. Please note that this tutorial does not apply to the Flex 3 framework.

This tutorial assumes a basic understanding of Flex, Haxe, AS3 and MXML. Note that this tutorial was developed and tested with the full release version of FP9. If you have a beta version you should upgrade to the latest version as applications developed with the SDK may not work with the beta (I had problems initially with this).

The examples below use a very minimal MXML file and AS3 class to initialise the Flex application and load an external SWF that contains Haxe classes compiled for Flash Player 9 byte code.

A minimal Flex application actually contains quite a lot of code. You can see this if you tell the Flex compiler to keep the intermediary Actionscript files it generates from a MXML file using the option -compiler.keep-generated-actionscript. There is a whole lot of initialisation going on and the boot process for a Flex application is reasonably involved.

Code for a Flex application is spread across two separate frames in the movie. The first contains the SystemManager and loader classes that initiate the loading process and the second frame contains the rest of the application code. This allows code on the first frame to load and execute quickly, monitoring the loading of the remainder of the application, and showing the user a loading progress indicator.

Ideally you'd want to compile your miminal Flex application with mxmlc and then merge your compiled Haxe classes into the second frame of the generated SWF. Since I'm not aware of a way to do that, I instead focused on getting my Flex application to dynamically load an SWF containing my Haxe classes and getting AS3 classes to create and call Haxe classes and vice versa.

A Minimal Flex Application

Create a new file with the following MXML code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:base="*">
   <base:ApplicationCanvas/>
</mx:Application>

Save it as haxeflex.mxml. This is a very minimal MXML file that simply adds an instance of class ApplicationCanvas onto the stage. We'll define ApplicationCanvas in a separate AS3 file. Create a new file named ApplicationCanvas.as and add the following code to it:

package {
   import flash.display.*;
   import flash.net.URLRequest;
   import flash.events.Event;
   import mx.core.*;
   import mx.controls.*;
   import mx.containers.*;
   import flash.system.ApplicationDomain;
   import flash.system.LoaderContext;


   public class ApplicationCanvas extends Canvas {

      public function ApplicationCanvas() {

         // load haxeApplication swf
         var ldr:Loader = new Loader();
         var swfUrl:String = "haxeApplication.swf";
         var req:URLRequest = new URLRequest(swfUrl);
         var ldrContext:LoaderContext = 
            new LoaderContext(false, ApplicationDomain.currentDomain);
         ldr.load(req, ldrContext);
         ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded);
      
         // Nested callback function for SWF loading
         function swfLoaded(e:Event):void {
            // TODO - load an instance of the HaxeApplication class
         }
      }
   }
}

Finally, compile the application using the mxmlc compiler (make sure this is on your path):

mxmlc haxeflex.mxml

This produces a SWF file call haxeflex.swf.

Creating the Haxe Library

Lets create a basic SWF containing a single empty Haxe class that we can add to later. Create a new file called HaxeApplication.hx:

class HaxeApplication {

   // contructor
   public function new() { }

}

Compile the Haxe application like so:

haxe -swf-version 9 -swf haxeApplication.swf HaxeApplication

This will produce a SWF called haxeApplication.swf containing our single empty class.

Loading the Haxe Library

By default the Flash Player's security sandbox model doesn't allow a movie loaded off the file system to load another such movie. I'm sure there's a way around this but I avoided this by simply accessing the SWFs via a webserver (I used Apache installed locally). So to run what we have so far, copy the two SWFs produced so far into your webserver's document root and load it via your web browser. E.g. browse to:

http://localhost/haxeflex.swf

If all goes well you will simply see an empty grey Flex application canvas. If you get this far without an error, Flex has successfully loaded the SWF containg the Haxe class.

Creating instances of Haxe Classes from AS3

To create an instance of our HaxeApplication class requires two steps: load the definition of the class and then use the new operator with that definition to create an instance of the class. Replace the content of function swfLoaded in ApplicationCanvas.as with the following code:

// Get the definition of the HaxeApplication class from the application domain
var haxeApplicationDef:Class = 
   ApplicationDomain.currentDomain.getDefinition("HaxeApplication") as Class;

// Use the new operator to create a new instance of the class
var haxeApplication:Object = new haxeApplicationDef();

Recompile the haxeflex.mxml as before and load it through your browser. You'll see nothing different but if there are no errors, you have succesfully created an instance of the HaxeApplication class from within your AS3 code.

Creating and Calling AS3 Classes from Haxe

The final step in this example is to have our HaxeApplication instance create a new Flex button component instance and return it to our calling AS3 canvas instance which will in turn add it as a child of itself.

In order to create an instance of a non-Haxe class, we need to provide the compiler with details of the public interface for that class. We do this by creating external class declarations - barebones class declarations that show only public methods and properties and use the extern keyword to tell the compiler that these classes are compiled separately.

In order to give the compiler access to all the mx classes, you'll have to install the Flex Haxe Library by running the following command :
haxelib install flex

Now, you can simply add -lib flex to your project options before compiling with Haxe.

Now that the compiler knows about the Flex Button component class, we can import it into our code, create an instance of it and set properties on it as if it was a normal Haxe class. Add the following import declaration and new method definition to HaxeApplication.hx and recompile it:

import mx.controls.Button;

//-- SNIP --

public function getButton():Button {
   var button:Button = new Button();
   button.label = "Hello Flex world from Haxe";
   return button;
}

Next, adjust ApplicationCanvas.as to call the new getButton method. Add the following to the swfLoaded callback function:

// fetch the button instance - call to a Haxe class
var button: Button = haxeApplication.getButton();

// add the button to the canvas
addChild(button);

Recompile the MXML application and reload haxetest.swf in your browser. You should see a grey canvas containing a single push button with the words Hello Flex world from Haxe as its label.

Our AS3 based Flex application is creating a new instance of our Haxe based HaxeApplication class and calling a method on it, which in turn is creating and returning an instance of a Flex AS3 class. We can now communicate bidirectionally between Haxe and Flex/AS3.

version #7963, modified 2010-01-25 22:02:46 by jjdonald