-
Fun with flash.utils.Proxy and events
Posted on September 24th, 2009 No commentsUPDATE
Following the below post, some more experimenting gave a much cleaner result, as shown here :-
var manager:EventManager = EventManager.getInstance(mySprite);
-
// add some event listeners
-
with (manager.assign(myOnMouseEventHandler)) {
-
click++;
-
mouseOver++;
-
mouseOut++; // add listener
-
mouseOut- -; // remove listener
-
}
-
// delete a listener automatically after it has triggered once
-
with (manager.assign(myOnLoadHandler, true)) {
-
complete++;
-
}
-
// use a predefined function to just trace some events
-
with (manager.assign(EventManager.CAPTURE_TRACE)) {
-
complete++;
-
}
Using ++ or - - will add or remove the specified listener for an object.
See the original post below on what’s going on.
new source.ORIGINAL POST
Lately, many people have been complaining about the cumbersome usage of the AS3 events model, we can only dream of a simple implementation in the lines of ‘myObject.listeners += dispatcher’ instead of ‘myObject.addEventListener(eventType, dispatcher, false, 0, true)’.Now there’s really not much of an alternative in AS3, one thing that remotely comes to mind is the flash.utils.Proxy class.
A quick glance at the help page shows promise, you can override accessor function such as getProperty and setProperty. Looking at the typing of the function arguments would suggest that you can pass any data type to these functions, as name, value and return are all noted with an asterix sign.
However, in reality the name argument can be of only two types, String or QName.That’s a bummer because that means you can not get the same functionality which the Dictionary class providers, namely to use a variable of any type as name argument.
Imagine this line of code :
-
EventManager.target(mySprite)[[MouseEvent.CLICK, onClick]]++;
-
// add callback
-
EventManager.target(mySprite)[[MouseEvent.CLICK, onClick]]- -;
-
// remove callback
EventManager is a factory class, it checks if mySprite was previously added as target, if it was the EventManager instance for mySprite which already exists is returned, if it’s a first timer, a fresh new EventManager() with mySprite as locally stored ‘target’ is returned.
Since EventManager extends Proxy, the syntax [[MouseEvent.CLICK, onClick]] would send the Array [MouseEvent.CLICK, onClick] as name:* argument to the setProperty method.
Unfortunately, since name:* is automatically converted to String or QName, the Array gets passed as Array.toString(), tracing to something like “click,function Function() {}”.
Okay for click, but the function reference is completely lost now…Should this have worked without the String cast, I would be able to capture the ++ and - - instructions to actually add or remove listeners.
The setProperty would check if name:* is an Array, and if so store that Array somewhere, then have the setProperty function return a reference to the EventManager instance itself (return this);++ would be captured then, again by the setProperty method, and would be detectable since the value:* attribute would be 1, or -1 for - -.
Upon reaching to this code, I could address the locally stored event Array from above and call addEventListener or removeEventListener based on the 1 or -1 value.Being stubborn and all, I did want something useful to emerge out of this experiment. The big trouble is sending the event handler function to the EventManager.
I did end up with the following structure, first imagine the next few code lines :-
mySprite.addEventListener(MouseEvent.CLICK, onMouseEventA, false, EventPriority.BINDING, true);
-
mySprite.addEventListener(MouseEvent.MOUSE_OVER, onMouseEventA, false, EventPriority.BINDING, true);
-
mySprite.addEventListener(MouseEvent.MOUSE_OUT, onMouseEventA, false, EventPriority.BINDING, true);
-
mySprite.addEventListener(MouseEvent.CLICK, onMouseEventB, false, EventPriority.BINDING, true);
-
mySprite.addEventListener(MouseEvent.MOUSE_OVER, onMouseEventB, false, EventPriority.BINDING, true);
-
mySprite.addEventListener(MouseEvent.MOUSE_OUT, onMouseEventB, false, EventPriority.BINDING, true);
-
mySprite.addEventListener(Event.ENTER_FRAME, onEvent, false, 0, true);
-
mySprite.addEventListener(ToolTipEvent.TOOL_TIP_SHOW, onEvent, false, 0, true);
-
mySprite.addEventListener(ToolTipEvent.TOOL_TIP_HIDE, onEvent, false, 0, true);
That’s a long list of code, just to add a number of events to some EventDispatcher.
Now thanks to some fiddling with the return values of the setProperty method, the following line of code (seperated by line breaks and tabs for the sake of readability) does the exact same thing :-
EventManager.target(mySprite)
-
[MouseEvent.CLICK][MouseEvent.MOUSE_OVER][MouseEvent.MOUSE_OUT][true]
-
(onMouseEventA, EventPriority.BINDING)
-
[MouseEvent.CLICK][MouseEvent.MOUSE_OVER][MouseEvent.MOUSE_OUT][true]
-
(onMouseEventB, EventPriority.BINDING)
-
[Event.ENTER_FRAME][true]
-
(onEvent)
-
[ToolTipEvent.TOOL_TIP_SHOW][ToolTipEvent.TOOL_TIP_HIDE][true]
-
(onEvent);
Notice how you can keep chaining parameters.
The [true] parameter acts as a breakpoint, it tells the setProperty method to apply all event types to the event handler function as noted in the next segment ie (onMouseEventA, EventPriority.BINDING).
When all is applied, it returns yet again a reference to itself (return this), so that future event chaining may proceed.In the same fashion you can remove listeners :
-
EventManager.target(mySprite)
-
[MouseEvent.CLICK][MouseEvent.MOUSE_OVER][MouseEvent.MOUSE_OUT][false]
-
(onMouseEventA);
-
// removes specific event type and event handler combo.
-
EventManager.target(mySprite)
-
[MouseEvent.CLICK][MouseEvent.MOUSE_OVER][MouseEvent.MOUSE_OUT][false]
-
();
-
// removes ALL event handlers which handle mouseOver and mouseOut
-
EventManager.target(mySprite)[false]()
-
// remove any active event handler for any event type
Is all this worth the trouble? Probably not, but I did have some fun messing with the flash.utils.Proxy class and deviating from its traditional use
Below is a small example of the whole thing in action :
The black box listens to some mouse events (out, over, click)This movie requires Flash Player 10Should you be interested, the source can be found here.
Leave a reply
-


