Using Flex components in Haxe with SWFMill and without external loading - part 1

16.08.2007 21886 2

To do that, we need first make a SWF with the Flex SDK compiler (mxmlc).
This SWF will make Flex initializations.
This SWF could be used as simple swf-library, while compiling with Haxe... but for some dark reasons, this one kills all Haxe initializations ! (no static main() called, almost nothing done...)
So, the trick is to call our Haxe class entry point inside the Flex code :
FlexApp.as :

package
{
    import mx.core.Application;
    import mx.events.FlexEvent;
    import mx.styles.StyleManager;
    import mx.styles.CSSStyleDeclaration;
    import mx.skins.halo.HaloBorder;
    
    import flash.utils.getDefinitionByName;
    import mx.core.SpriteAsset;
        
    public class FlexApp extends Application
    {
        public static var instance : FlexApp;
        
        public function FlexApp() : void
        {
            super();
            
            trace( SpriteAsset ); // force class to be included
            
            instance = this;
            
            this.layout = "absolute";
            this.addEventListener(FlexEvent.CREATION_COMPLETE, handleComplete);
            var style : CSSStyleDeclaration = new CSSStyleDeclaration();
            style.setStyle( "borderSkin", mx.skins.halo.HaloBorder );
            StyleManager.setStyleDeclaration( "Application", style, false );
        }
        private function handleComplete( event : FlexEvent ) : void
        {
            // It call the Main Haxe class from here
            var MainHxClass : Class = getDefinitionByName( "Main" ) as Class;
                        var instanceMainHx : Object = new MainHxClass();
        }
    }
}

As we can see, in handleComplete, we instanciate our haxe Main class, which looks like :
Main.hx :

import mx.controls.Button;
import mx.styles.StyleManager;
import mx.styles.CSSStyleDeclaration;
class UpState extends mx.core.SpriteAsset{}
class OverState extends mx.core.SpriteAsset{}
class DownState extends mx.core.SpriteAsset{}
class Main
{
    public function new()
    {
        __initFlex();
            
        var button = new Button();
        button.label = "Flex Button :)";
        
        FlexApp.instance.addChild( button );
                
        var tf = new flash.text.TextField();
        tf.text = "texte";
        
        var m = new flash.display.MovieClip();
        m.graphics.lineStyle( 1, 0x000000, 1 );
        m.graphics.lineTo( 20, 20 );
        
        flash.Lib.current.addChild( m );
        flash.Lib.current.addChild( tf );
    }
    
    function setupStyles() : Void
    {
        var style = new CSSStyleDeclaration();
        style.setStyle( "textAlign", "left" );
        style.setStyle( "fontAntiAliasType", "advanced" );
        style.setStyle( "fontGridFitType", "pixel" );
        style.setStyle( "paddingLeft", 10 );
        style.setStyle( "paddingRight", 10 );
        style.setStyle( "paddingTop", 5 );
        style.setStyle( "paddingBottom", 5 );
        style.setStyle( "horizontalCenter", 0 );
        style.setStyle( "verticalCenter", 0 );
        
        style.setStyle( "upSkin", UpState );
        style.setStyle( "overSkin", OverState );
        style.setStyle( "downSkin", DownState );
        StyleManager.setStyleDeclaration( "Button", style, false );
    }
    
    function __initFlex()
    {
        setupStyles();
        var mc = new flash.display.MovieClip();
        FlexApp.instance.parent.addChild( mc );
        flash.Lib.current = mc;
    }
}

We need also an extern class FlexApp.hx to prevent compilation errors :
FlexApp.hx :

import flash.display.MovieClip;
extern class FlexApp extends MovieClip
{
    public static var instance : FlexApp;
}

Then to combine SWF assets and the Flex SWF, we need SWFmill:
library.xml :

<movie width="320" height="240" framerate="12" version="9">
  <frame>
    <clip import="FlexApp.swf"/>
    <library>
        <clip id="UpState" import="assets/up.png" />
        <clip id="OverState" import="assets/over.png" />
        <clip id="DownState" import="assets/down.png" />
    </library>
  </frame>
</movie>

With that, we get one single Haxe SWF, with a Flex component (here button).

Download sample here

Notes:

  • Flex SWF can be build once for all your Haxe projects. You can use it seeveral times, since the Haxe Main class name is the same.
  • You need Flex 3 SDK externs classes, you can download them here
  • In the Haxe Main class, you can't use some low-level function (like trace...), because of Haxe bad initialization (I think)
  • flash.Lib.current is overwrited with the FlexApp parent instance, you can hang assets on it as usual (after __initFlex)
  • Flex components must be hanged not on flash.Lib.current, but on special FlexApp.instance
  • You need skins for Flex components (assets from SWFMill)

It looks a bit complicated, but it isn't finally.
The only strange thing to fix, is the Haxe initialization. If you have any ideas, don't hesitate to leave comments or contact me.
Thanks for reading ! ;)

Commentaires

15.08.2007 à 16:47 Ruy

Very nice, but there's no hope for the flex default skin work? It still looking too much hard work...
But this is a really great beggining!
Keep on with all your stuff!

15.08.2007 à 20:19 Michal

Hi! Thanks you!
Well, Flex default skin (like halo) are in Assets.swf in the halo theme SWC. Some of the assets have lower-case begining class name, and could be difficult to use with Haxe (doesn't accept lower case class names, only packages). That a first reason...that we could find a work-around . Second reason why I use custom skins is that for some components (that could be scaled i.e.),  the assets are scale9grid cut out, and I didn't find at this time (and didn't really searched for that ) the way and the place, they are assembled.
Anyway, as I said, it's a first try, and by the way, I would, at least, show the Flex components behaviour in Haxe that work well for now.
Don't hesitate to post improvements if you find something !

Laisser un commentaire

http://
×