EventDispatcher Usage Revisited

I had a problem in an app I was building at home for fun in Central. As the app got more complex, I started adding more and more events that I needed my AppController to keep track of. AppController being a class that runs as the Singleton in the Application part of Central. For things totally unrelated, it was pretty easy to map the events generated by a player such as “play” to a class method called “play”, and for a Playlist’s “selectedIndexChange” to be mapped to a class method of “selectedIndexChange”. However…

Comments

10 responses to “EventDispatcher Usage Revisited”

  1. erik bianchi Avatar

    w3 on the DOM stuff not ecma.

    I have a secretary?

  2. JesterXL Avatar

    No d00d, you just check email every 5 minutes… I’m impatient.

  3. JesterXL Avatar

    Er, actually, I think you were out to lunch…

  4. JesterXL Avatar

    Grr… It’s not working in Central. I think, however, this is a problem with EventDispatcher losing scope because it works up until the point dispatchEvent is called… the problem is (what I said would never happen) is that the function is running in the scope of the homeskillet that is generating the event. Heck with this, I’m using Grants…

  5. erikbianchi Avatar

    but it works in flash? If so export to Flash 6 and see if that makes a difference??

  6. JesterXL Avatar

    Central is 6.0.65.0, so I don’t really have a choice…

  7. darron Avatar

    Use Mike Chamber’s EventProxy: http://www.markme.com/mesh/archives/004286.cfm

    usage:
    my_btn.addEventListener(“click”, new EventProxy(this, “onButtonClick”));

  8. darron Avatar

    Note to self. Read your entire post before posting a comment. ;-)

  9. JesterXL Avatar

    It’s all good; I re-read his post based on your suggestion in case I missed something; and indeed I did. His class is actually a Responder like object that forwards the event. However, with the amount of event’s I’m registering, I’ve kept to my base class using EventDispatcher, and therefore have little overhead.

    …or maybe I’ve switched my event engine too much in my Flash career and am just too tired today to switch again. Maybe tomorrow.

  10. erikbianchi Avatar

    oh I see the problem. In the EventDispatcher if what you are adding is a method (function) it applys the function to the queueObj. However, I beleive that applything the method to the queueObj was an oversight. By changeing the apply in the dispatchQueue method from this:

    o.apply(queueObj, [eventObj]);

    to this:

    o.apply(eventObj.target, [eventObj]);

    Allows the event dispatcher to use the proper scope if one is provided. If not the scope remains unchanged from the current functionality.

    I’ve come to this conclusion for a couple reasons:

    1) everything *seems* to work as intened and scope is being applied correctly.

    2) The following code from the dispatchEvent method seemed odd because it was not being used anywhere else in the class and it logically looked like it would solve any scope issues.

    if (eventObj.target == undefined)
    eventObj.target = this;

    At anyrate here is a working example using my edited EventDispatcher method (free typed in here might be some typos):

    // SUBJECT
    class Subject
    {

    // Interface for EventDispatcher
    // didnt want to type a interface, lazy
    public var dispatchEvent:Function;
    public var addEventListener:Function;

    // Instance name used to identify scope
    private var name:String = “Subject”;

    // Constructor inits Dispatcher
    public function Subject()
    {
    EventDispatcher.initialize(this);
    }

    // broadcast the event uses target to pass in scope
    public function triggerUpdate(scope){
    dispatchEvent({type:”update”,target:scope});
    }

    }

    // Observer: Class that Watches Subject
    class Observer
    {

    private var m_Subject:Subject;
    private var name:String = “Observer”;

    public function Observer()
    {
    m_Subject = new Subject();
    m_Subject.addEventListener(“update”,onUpdate)
    }

    public function onUpdate()
    {
    trace(“Updated: “+name);
    }

    // trigger event and passes scope
    public function triggerUpdate()
    {
    m_Subject.triggerUpdate(this);
    }

    }

    // root timeline
    var name = “root”;
    function update(){
    trace(name);
    }

    // uses the timeline as the listener
    var TestSubject = new Subject();
    TestSubject.addEventListener(“update”,update);
    TestSubject.update();

    // uses a class as the listener
    var TestObserver = new Observer();
    TestObserver.triggerUpdate();