The v2 component architecture introduced a new event dispatching and handling framework, in which event objects are produced by components and consumed by whatever listeners are attached to them. For more information on this, refer to the Flash documentation under “Using the event object”. The following sample code illustrates the basic principles.

listener = new Object();
listener.click = function(evtObj) {
trace("Button clicked: "+evt.target);
}
myButton.addEventListener("click", listener);

The myButton component generates a “click” event when pressed using the following code:

this.dispatchEvent({type:"click", target:this});

which creates a new (anonymous) event object (with the requisite type and target properties) and submits it to the event handling framework. The event framework then passes the event along to the listener object, which itself was previously registered as a listener for events of type “click” coming from myButton.

One very nice feature of the new event framework is that it is also possible to use it outside the context of v2 components. This can be useful, for example, when creating a modular application in which various elements need to communicate with one another yet making those elements into full-fledged components would be overkill.

Any object can be made into an event producer by invoking the EventDispatcher mix-in. A mix-in is a special class that dynamically adds methods and fields to a given object in order to expand its functionality. Such constructs are used liberally throughout the core classes in Flash MX 2004. Using the EventDispatcher mix-in adds the following methods to a given object:

dispatchEvent(evtObj):Void

Dispatches the given event object to the event framework, allowing it to be sent to any attached listeners

addEventListener(eventType:String, handler):Void

Registers the specified handler object as a listener for the specified event type coming from the current object

removeEventListener(eventType:String, handler):Void

Unregisters the specified handler for the specified event type

An additional method called dispatchQueue is also added, but that method is for internal use by the event framework.

In order to add these events to an object, simply invoke EventDispatcher.initialize:

class MyCalendar extends MovieClip {

public function MyCalendar(Void) {
...
// this adds (mixes in) the dispatchEvent, etc. methods
mx.events.EventDispatcher.initialize(this);
}
...
}

Once the initialize method is invoked at runtime, the MyCalendar class will have dispatchEvent and the add/remove listener methods, and will work just like any other event producer in the event framework.

One problem with the fact that the event methods are added through a mix-in at runtime is that the compiler won’t know about those methods while it is compiling the class. Therefore, if we just invoke dispatchEvent within the example class above, the compiler will generate an error since dispatchEvent isn’t defined within MyCalendar or within MovieClip, its superclass.

There are two ways to get around this problem. The easiest is just to define three additional class fields of type Function, one for each method that’s going to be added by the mixin:

class MyCalendar extends MovieClip {

var dispatchEvent:Function;
var addEventListener:Function;
var removeEventListener:Function;

public function MyCalendar(Void) {
...
// this adds (mixes in) the dispatchEvent, etc. methods
mx.events.EventDispatcher.initialize(this);
}
...
}

A slightly more rigorous method is to add a “stub” for each of the mix-in methods, which will be overridden once the mix-in attaches the real methods at runtime but will satisfy the compiler in the meantime. Write the stubs to throw Errors by default, just to make sure that the mix-in did in fact override those methods as expected:

class MyCalendar extends MovieClip {

public function MyCalendar(Void) {
...
// this adds (mixes in) the dispatchEvent, etc. methods
mx.events.EventDispatcher.initialize(this);
}

public function dispatchEvent(evtObj):Void {
throw new Error("dispatchEvent method not overridden!");
}

public function addEventListener(eventType:String, listener) {
throw new Error("addEventListener method not overridden!");
}

public function removeEventListener(eventType:String, listener) {
throw new Error("removeEventListener method not overridden!");
}

...
}

By doing this, the compiler will see that MyCalendar does in fact define the event methods, even though those methods will be overridden at runtime by the EventDispatcher class.