Archive for the ‘Action Script’ Category

Patching NetStreamClient

(February 14th, 2010)

I couple of days ago I noticed that my conceptual NetStreamClient was failing when connecting it towards a NetStream, the debugger threw errors regarding missing a Proxy implementation of getProperty.

The problem was when building the class I took for granted that NetStream referenced against the client object and invoked the callback function from the object when a callback took place. But the fact is that when you assign a client object to netstream it saves a reference to the callback function, not the client object itself. So it was clear why my class didnt work.

So I patched it up with the proxy implementation getProperty (it looks a bit hackish but it does the trick).

flash_proxy override function getProperty(name:*) : *
{
        var qName:QName = name as QName;
       
        return function ( args ) : void
        {
                flash_proxy::callProperty( qName, args[0] );
        }
}

I also noticed that in my usage example I used an object instead of the NetStreamClientEvent. So this is how you “really” use it.

// create a instance
client = new NetStreamClient();
// assign the client
netStream.client = client;
// then just add listeners to the client
client.addEventListener( NetStreamClientEvent.CUE_POINT, client_cuePointHandler );

// an example of the handler function
function client_cuePointHandler ( event:NetStreamClientEvent ) : void
{
        // the info object holds the original data
        var info:Object;
                       
        info = event.arguments[0];
                       
        trace( [info.name, info.time, info.cuetype] );
}

Updated classes here: Download it here here, or view the NetStreamClient class here.

A nicer way of using NetStream.client

(January 11th, 2010)

* UPDATE: This class has been patched

After working with the NetStream class for quite some time it has always striken me how badly the “client” approach is.

Default behaviour

netStream.client = {onCuePoint:myCuePointCallback};

function myCuePointCallback ( point:Object ) : void
{
}

Basicly to retrive a cue point we have to assign the client property with a object populated with a needed set of callback functions, that in the end will be triggered by the NetConnection class. You rarely see this callback mechanism in as3 and it can easly get a bit confusing, mainly beacuse you need to remember the callback function names.

So I made a specific client class for NetStream which extends the Proxy util and converts the callbacks into actual events with EventDispatcher. It works like this.

Usage

// create a instance
client = new NetStreamClient();

// assign the client
netStream.client = client;

// then just add listeners to the client
client.addEventListener( NetStreamClientEvent.CUE_POINT, client_cuePointHandler );
client.addEventListener( NetStreamClientEvent.META_DATA, client_metaDataHandler );

// an example of the handler function
function client_cuePointHandler ( info:Object ) : void
{
        trace( [info.name, info.time, info.cuetype] );
}

The NetStreamClient covers the most used callbacks (such as metadata, play status), and the callbacks it cannot identify gets labeled as a Unknown call.

Try it out and just shout if you have any comments!
Download it here here, or view the NetStreamClient class here.

/ Martin

Dealing with the NetStatus info codes

(November 16th, 2009)

I never liked dealing with the NET_STATUS info codes that NetStream generates, beacuse I always forget the different codes. And there is no built in class which holds the string constant as representations for the different codes. So I basicly did a very simple wrapping of the status codes from the Adobe Reference into a simple to use class.

Usage

protected function netStream_netStatus ( event:NetStatusEvent ) : void
{
        switch( event.info.code )
        {
                case NetStatusConstants.NETSTREAM_PLAY_START:
                        trace("Start!");
                        break;
        }
}

So if you are like me, with a memory like a pacific sea turtle, this might come in handy. Download it here here, or view the class here.

PureMVC hints and tips

(October 11th, 2009)

PureMVC has been my framework of choice for the last 18 months, the beginning of our relationship was a bit rocky but after a while we got to know each outher. Now, looking back at atleast the ten bigger projects I have done since, I’d say we know one another well, so well that I have learned a bunch of new hints and tips. Something I thought I might aswell share on this blog.

Im not only making this little article as a reflection of my past experiences, but also to mark a new start for me with my new framework of choice RobotLegs, and this felt like a good way to end things :) In time I might go back to using PureMVC, perhaps not. PureMVC is anyway a great framework and alot of fun, so I hope some of these puremvc tips comes in handy!

1. Dare to use Proxies
The hardest part for me was to use Proxies. In the beginning I often ended up using a mediator when I could have used a proxy instead. Take a look at these examples.

SizeProxy = This Proxy listens for stage resize events and sends out resize notifications all through the application. In the past I embedded this functionality into a mediator called ApplicationMediator.

AddressProxy = This Proxy takes care of all state management related data, and do everything from setting, retriving, formatting and finally sending out notifications. In the past I had this functionality into a mediator aswell. (Shame on me!)

2. Keeping track of your proxies and mediators
Avoid always re-typing string representations when dealing with proxies and mediators. Add a static constant variable named NAME in your classes and refer to that variable any time you need to access the proxy/mediator. Like this.

The class

package se.marteinn.puremvc.single.view
{
        import org.puremvc.as3.interfaces.IMediator;
        import org.puremvc.as3.patterns.mediator.Mediator;

        public class ApplicationMediator extends Mediator implements IMediator
        {
                public static const NAME:String = "applicationMediator";
        }
}

Registrating the mediator

this.facade.registerMediator( new ApplicationMediator( ApplicationMediator.NAME, application ) );

Retriving the mediator

this.facade.retriveMediator( ApplicationMediator.NAME ) as ApplicationMediator

Aww, you get the idea!

3. Dont forget your OOP
Remember that Mediators are still classes that you can extend. So dont be afraid to make your own “abstract” classes.

Like this

package se.marteinn.puremvc.single.view.states
{
        import org.puremvc.as3.interfaces.IMediator;
        import org.puremvc.as3.patterns.mediator.Mediator;

        public class StateMediator extends Mediator implements IMediator
        {

                public function StateMediator(mediatorName:String=null, viewComponent:Object=null)
                {
                        super(mediatorName, viewComponent);
                }

                public function singJohnnyCash ()
                {
                        trace( “Ring of fire” );
                }
        }
}

And then extending it.

package se.marteinn.puremvc.single.view.states
{
        import se.marteinn.puremvc.single.view.states.StateMediator;
        import org.puremvc.as3.interfaces.IMediator;

        public class PageStateMediator extends StateMediator implements IMediator
        {
                public function PageStateMediator(mediatorName:String=null, viewComponent:Object=null)
                {
                        super(mediatorName, viewComponent);

                        singJohnnyCash();
                }
        }
}

4a. Be nice to the commands
Keep them as clear and as re-usable as possible. Try not to manipulate mediators directly in the command, use notifications instead. (Since its all ok for a mediator to retrive notifications).

4b. But use a command whenever you can
Commands makes your application easier to understand and to work with, so use commands whenever it feels right.

5. Organizing notifications
Placing all notifications into one class (placed in the application root) helps keeping track of things.

package se.marteinn.puremvc.single
{
        public class ApplicationNotifications
        {
                public static const STARTUP:String = "startup";
               
                // preload related
                public static const INIT_PRELOAD:String = "initPreload";
                public static const START_PRELOAD:String = "startPreload";
               
                public static const LOAD_CONFIG:String = "loadConfig";
                public static const CONFIG_LOADED:String = "configLoaded";
               
                // yada yada..
        }
}

And its easy to access

sendNotification( ApplicationNotifications. STARTUP );

6. Organizing parameters
To place values the application needs to actually work, such as api keys and values you dont want to store in a external config file, into its own class is a good idea.

package se.marteinn.puremvc.single
{
        public class ApplicationParameters
        {
                public static const GOOGLE_MAPS_API_KEY:String = "asd234234dssdf";
        }
}

And its easy to access

loadStuff( ApplicationParameters. GOOGLE_MAPS_API_KEY );

7. Use onRegister whenever you can on your proxies and mediators
My advice is not to place construction code into the constructor of proxies/methods, instead override the onRegister method and place your code there. It makes you code easier to read and give you less bugs in the future (when porting a app to multicore). Read more here http://lowpitch.com/blog/puremvc-multicore-vs-standard-singlecore/

8. The namespace
So, how should a PureMVC namespace be organized? Well, a namespace can be organized in many forms, this is my way in doing it.

se.marteinn.project
        controller     
                vo
                        (My controller specific VO:s here)

                (My commands here)

        model
                vo
                        (My model specific VO:s here)
                services
                        (My model specific services here)

                (My proxies here)
               
        view
                               
                components
                        (View related components here)
       
                (My mediators here)

        ApplicationFacade
        ApplicationNotifications
        ApplicationParams

It could also look like this:

se.marteinn.project
        controller     
                vo
                        (My controller specific VO:s here)
                commands
                        (My commands here)

        model
                vo
                        (My model specific VO:s here)
                services
                        (My model specific services here)
                proxies
                        (My proxies here)
               
        view
                               
                components
                        (View related components here)
                mediators
                        (My mediators here)

        ApplicationFacade
        ApplicationNotifications
        ApplicationParams

9. Adding a interface to the application main class
To make things as flexible as possible and to simplify when installing my puremvc base into a new application, I have a interface called IApplication, where the main Application implements IApplication. That way:

The application class can be named whatever, as long its implementing IApplication…

package
{
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
       

        import se.marteinn.puremvc.single.IApplication;

        [SWF(frameRate="31", backgroundColor="#000000")]
        public class TestApp extends Sprite implements IApplication
        {
               
                protected function draw () : void
                {
                        ApplicationFacade.getInstance().startup( this );
                }
               
        }
}

…the facade will be fine with it

package se.birth.puremvc.single
{
        import org.puremvc.as3.interfaces.IFacade;
        import org.puremvc.as3.patterns.facade.Facade;
       
        import se.marteinn.puremvc.single.controller.StartupCommand;

        public class ApplicationFacade extends Facade implements IFacade
        {
                protected static var instance:ApplicationFacade;
               
                public static function getInstance () : ApplicationFacade
                {
                        if( instance == null )
                                instance = new ApplicationFacade ();
                        return instance;
                }
               
                override protected function initializeController():void
                {
                        super.initializeController();
                       
                        this.registerCommand( ApplicationNotifications.STARTUP, StartupCommand );
                }
               
                public function startup ( application:IApplication ) : void
                {
                        this.sendNotification( ApplicationNotifications.STARTUP, application );
                }
               
        }
}

Read more
If you are looking for more advice and thoughts on how to build better PureMVC applications, look at these links:

10 tips for working with PureMVC by Jens Krause
http://www.flex-labs.de/blog/2008/10/10-tips-for-working-with-puremvc-by-jens-krause/

Building a Flash site using PureMVC
http://hubflanger.com/building-a-flash-site-using-puremvc/

My own PureMVC collection of links (both Singlecore and Multicore)
http://delicious.com/marteinn/puremvc

Last but not least, the PureMVC.org website with the all mighty guru of know it all Cliff Hall
http://www.puremvc.org/

Cheers!
/ M

Note to self: Robotlegs and injections

(October 11th, 2009)

When injecting a instance (or whatever) in robotLegs be sure to spell inject with a capital “I”.

Bad

[inject]
public var pageOnFrontProxy:PageOnFrontProxy;

Good

[Inject]
public var pageOnFrontProxy:PageOnFrontProxy;

#tweetcoding: 01 – First try

(February 19th, 2009)

This is my first attempt on the tweetcoding contest held by grant skinner… and I do have to say thats its very funny indeed :)

Note that this example does not fully use object ‘o’ for persistant data, yet. And to save place I also had to shortcut Math.cos (but hey, evertyhing is till in the 140 char span, sorry 139 chars)

if(!i)o.h=50+r()*50,g.clear(),v=.2,c=m.cos;//43 chars
ls(1,0,.4+c(i*v)*.6);//21 chars
(!i?mt:lt)(m.sin(i*v)*(i*v*.2),c(i*v)*o.h-i*.1+o.h);//52 chars
(i>o.h*.2*100)?i=0:i++;//23 chars

Compiled entry here.

More about the competition here.

If time allow, its possible that I will attempt to do a few variations before the final sumbit.

/ M