Monthly Archives: October 2005

Impatiently Waiting for ActionScript 3

I spent the morning today reading up on the future of Flash over at Macromedia Labs. This new repository for pre-release alpha software is bursting with information on Flex 2, ActionScript 3, and the Flash 8.5 plugin. There are so many new features that will make the life of every AS developer so much easier. I almost wish they had waited on this. I’m still exploring Flash 8, and now I’ll be waiting like a little kid for Christmas to actually put AS3 in production.

A lot of people have mentioned interest in regular expressions and E4X, but I’m looking forward to getting rid of all the hacks required to code AS. Firstly, MovieClips are now instantiated like regular variables. We won’t be laughing at newbies when they try this little number anymore:

var mc:MovieClip = new MovieClip();

Not only that, but subclasses can be declared like that too. No more messing with prototypes to get a component on the Stage with only code. Likewise, we don’t need to assimilate root with that method anymore anymore either because now it can be the class of our choice. MovieClips have become so flexible that suddenly there’s a large inheritance chain of specialized display objects. It starts all the way down from a new EventDispatcher class, which acts as a base, and goes up though half a dozen levels that add functionality at each step. Macromedia highlighted a Sprite class which is a perfect lightweight version of MovieClip for components.

Unfortunately, just two days after I presented my new event model, Macromedia announces that they’ve redesigned events from the ground up. If a class has any sort of event in AS2, it uses the newer model in AS3. There goes my hatred for non-standard events. Moreover, Delegate is no longer needed to specify a listener function. It’s built right into addEventListener. Finally, while listener functions still receive a single event object as an argument, there’s a base Event class that we can subclass. I got my strong typing, even if I still have to use the object. They covered every point I made, so I intend to switch back to their version once AS3 officially comes out.

I noticed other interesting tidbits while I skimmed over the docs. There’s a new protected keyword that effectively has the same functionality that private does now. This makes private stronger by hiding members from subclasses too. There’s also a const keyword for making constants. Sealed classes make dynamic properties and methods impossible at runtime. As a language feature, this isn’t necessarily good or bad (I can see arguments both ways), but if a class is sealed, there will be a performance increase, and less memory will be needed in the player. I saw a couple new primitive types–int and uint. They’ll be very useful for when floating points aren’t needed. Lastly, for those of us that will be migrating our code, we’ll no doubt deal with the fact that the mx namespace has been reorganized. Macromedia added many new levels in there, and moved quite a few classes around.

In short, we ActionScript coders are going to be spoiled with so many new tools at our disposal. I’m sure I’ll wish I could build a site in AS3 well before it’s out in final form, but I’m glad we have a lot of time to experiment and learn about the new features. AS3 has matured well beyond it’s years, and its core library definately got a great overhaul. It’s a good time to be a Flash developer.

Going Beyond EventDispatcher

Macromedia’s EventDispatcher class is used in almost every one of my Flash projects, and it’s the foundation for my component framework. Obviously, I find it’s functionality indispensable. However, it comes with limitations that I’d like to live without. For one, specifying a function name to call in a listener could be simpler. Delegate is useful, but having to use it for almost every event call makes it’s functionality a good candidate for encapsulation. I’ve also never been a big fan of the event object the listener receives as an argument. It uses Flash’s dynamic typing, which I admit can be useful at times. However, events tend to have uniform arguments, so I’d like it to be a little more type-safe. Ideally, I’d like the listener to receive these arguments like a regular function. With so many needs, I realized it was time to get down and dirty with events.

On a side note, I’d like events in other Macromedia classes to behave the same way. I usually have to check the documentation to remember which way to listen to a particular object. With some classes, you can only listen to all the events at once, and in others, there’s a specific function in the object that you have to implement, which will then be in that object’s scope. You’ll then have to hack your way out to access variables and methods in another object. Of course, I can’t replace the system used by some of these classes, they’re hardcoded into the player, but it’s not too hard to create a wrapper class that hides the clutter and utilizes my new event model to keep everything consistent.

This new event model involves two main classes: Event and EventManager. Event handles one specific event by keeping track of the listeners for that event and dispatching to them as requested. It works behind the scenes as part of EventManager. EventManager is the front end that acts as a repository for events. Every one of my components has one. It’s simple to add an event, then pass on any objects that want to listen to a specific event. Here’s a basic example of how a component sets up its EventManager:

import net.zeusdesign.events.EventManager;

class SomeComponent
{
	private var _eventManager:EventManager;
	function SomeComponent()
	{
		//instantiate the event manager
		this._eventManager = new EventManager();

		//the event is then added to the manager
		this._eventManager.addEvent("onSomeEvent");
	}

	public function get eventManager():EventManager
	{
		//It's easier for outside classes to listen to the EventManager
		//directly, so we don't have to implement add and remove methods
		//over and over.
		return this._eventManager;
	}

	public function someClassMethod(arg1, arg2):Void
	{
		//now, somewhere else in the class, I want to dispatch the event
		this._eventManager.dispatchEvent("onSomeEvent", [arg1, arg2]);
	}
}

An object that wants to listen to an event, can do so easily. You’ll notice I added a third argument to the standard addEventListener. I call this the routing function. This argument allows a listener to specify a specific function to call when the event is triggered. It can be very useful if you have many components that would normally have the same event name. Also, as you saw above, events are passed as an Array to EventManager, but when the event is triggered, the listener function receives arguments like a normal function instead of one event object like EventDispatcher.

var c:SomeComponent = new SomeComponent();
c.eventManager.addEventListener("onSomeEvent", this, "onCustomEventName");

function onCustomEventName(arg1, arg2):Void
{
	//do something
}

You can download the EventManager source code now. If you have any questions, comments, or improvements please leave a comment below.