views:

222

answers:

1

I have a question regarding as3 listeners, and instances of a class.

The main question: is there a way to dispatch an event from the button instance in such a way that the other button instances can listen (without the need for a listener in the document class)

Lets say i have a document class and a button class. The document will have several instances of the button class added to the display list. When a button is selected, the set method would be called to set the package variable of selected to that instance. It is from here i would like to dispatch an event to notify all other instances.

|document
|-button instance 1
|-button instance 2
|-button instance 3 (i want to send an event directly to instance 1 and 2...)

My current solution was to create a buttonGroup class, that instantiated the buttons, and the buttons would send an event call to the group parent.

|document
|-button group (catch the event and send an event to all instances within the group)
|---button instance 1
|---button instance 2
|---button instance 3 (dispatch  the event)

But my problem remained - if i had multiple groups and i wanted to send an event to all of the group instance.. then i would need a buttonManager class to keep track of the groups (or at least, this is how i understand it?)

|document
|-button manager (catch the event and send an event to all group instances)
|
|---button group 1
|-----button instance 1
|-----button instance 2
|-----button instance 3 (dispatch  the event)
|
|---button group 2
|-----button instance 1
|-----button instance 2
|-----button instance 3 (dispatch  the event)

I am not adverse to these "solutions", i am just curious if there is another way, or if in fact my solutions are a good practice. The basis for my code sits below (minus the button manager and group classes)

I hope this was descriptive enough, and be gentle, i am new to OOP... Thanks in advance.

document.as

import flash.display.*;
import flash.events.*;
import myClasses.events.ButtonEvent;

public class Document extends MovieClip {       

    public function Document(){
        trace("initialising Document...");
        addEventListener(Event.ADDED_TO_STAGE, popStageVars);           
    }   


    private function popStageVars(e:Event){
        trace("popping stage vars...")

        var ob1:AbstractOBJ = new AbstractOBJ           
        var ob2:AbstractOBJ = new AbstractOBJ           
        var ob3:AbstractOBJ = new AbstractOBJ

        addChild(ob1)
        addChild(ob2)
        addChild(ob3)


        ob1.selected = ob1
        ob2.selected = ob2
        ob3.selected = ob3

    }       

}

The button class:

import flash.display.*; 
import flash.events.*;
import myClasses.events.ButtonEvent;

public class ButtonOBJ extends MovieClip  implements IEventDispatcher {

    internal static var _selected:Object = null

    public function ButtonOBJ(){
        trace("initialising ButtonOBJ...");         
        addEventListener(Event.ADDED_TO_STAGE, popStageVars);
        addEventListener(AbstractEvent.SET_CUR, checkClip);
    }


    private function popStageVars(e:Event){
        trace("popping stage vars..." + this.name)
    }       

    private function checkClip(e:AbstractEvent){
        trace("checking button registered... " + this.name)
    }

    public function get selected():Object{
        return _selected                        
    }

    public function set selected(s:Object):void{
        var sName:String 

        if(selected != null){
            sName = selected.name
        }else{
            sName = null
        }

        trace(this.name + " is changing the current selected from: " + sName + " - to: " + s.name)          

        _selected = s
        dispatchEvent(new AbstractEvent(AbstractEvent.SET_CUR, true));  
    }       

}

and also the buttonEvent:

package myClasses.events{       

import flash.events.Event;

public class ButtonEvent extends Event {

    public static const SET_CUR:String = "setSelected";
    public static const VERSION:Number = 1.0;

    public function ButtonEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {         
        super(type, bubbles, cancelable);
    }

    public override function clone():Event {
        return new ButtonEvent(this.type, this.bubbles, this.cancelable);
    }   

}
}
+1  A: 

Your button class could add a listener to the stage. If your event bubbles, when the event is fired by the target, it'll bubble up to the stage. The button would "hear" the event and respond. I usually do what you are doing though and add the listener to a group. Then I loop through the buttons when the event is received and set "selected" if the event.target is the same as the current button in the loop.

Typeoneerror
If i understand correct - you are saying add a listener to the document class - but the buttons wont hear because the event bubbles to the top, and never hits the other instances - unless i am mistaken.The problem i have with that approach: it forces me to keep track of all the buttons created (an array, looping through dispatching method calls to instances), and loses the self-aware approach im looking for. This way is essentially the same as the group.Id love to keep all of the button management away from the document class...If i have misunderstood, would you mind elaborating?
Beans
Not the document class, but the stage. stage.addEventListener(); would be inside your button class.
Typeoneerror
Forrest for the trees huh? Thank you. I feel liek the man who lost his glasses only to find them on top of his head.As a footnote - adding a stage listener this way, is it considered bad form compared to the group and manager method?
Beans
I think so. Hence why I say I usually do the more involved group method. But it works quickly :) Maybe someone else will have a better answer done the line.
Typeoneerror