views:

172

answers:

4

I'm loading an external SWF (pre-made by an other department of the company I work for) using flash.display.Loader. I then traverse the display list, register all objects and listen for added/removed events to handle future changes to the list.

var obj:DisplayObjectContainer = loadEvent.currentTarget.content as DisplayObjectContainer;
var count:Number = obj.numChildren;
for (var i:Number = 0; i < count; i++)
{
     registerObject(obj.getChildAt(i));
}
obj.addEventListener(Event.ADDED, onChildAdded);
obj.addEventListener(Event.REMOVED, onChildRemoved);

The thing is I wonder what would happen if one of the developers of the original SWFs uses:

.visible = true / false;

Is there a way I can listen for changes to the .visible property? Or any other property (that doesn't fire a built-in event) for that matter?

+1  A: 

For DisplayObject you want to listen for the addedToStage and removedFromStage events.

For Flex components, listen to show and hide events.

Sam
That was my first guess. But will direct changes to .visible will trigger those event?
Leeron
Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE have nothing to do with the .visible property of a DisplayObject. These events will only fire when addChild/removeChild is called for the DisplayObject, *and* if that DisplayObject's parent is in the display list (a descendent of the MainTimeline).
+3  A: 

Not by default, I don't think. But you could create your own Event class and dispatch it from an override of function set Visible without a lot of hassle.

Edit: Okay, so a_w does have the right idea, and you can attach that right back into the container.

Make a wrapper like so:

public class VisibilityEnabledDisplayObject extends DisplayObject
{
    public function VisibilityEnabledDisplayObject(d:DisplayObject)
    {
        super();
        _d = d;
    }
    public function override get visible(b:Boolean):Boolean
    {
        return this._d.visible;
    }
    public function set visible(b:Boolean):void
    {
        if(this._d.visible != value)
        {
            this._d.visible = value;
            this.dispatchEvent(new Event('visibilityChanged'));
        }
    }
    private var _d:DisplayObject;
}

Then, make your loop look like:

for (var i:int = 0; i < count; i++)
{
    var do:DisplayObject = obj.getChildAt(i);
    registerObject(do);
    obj.removeChildAt(i);
    var vedo:VisibilityEnabledDisplayObject = new VisibilityEnabledDisplayObject(do);
    obj.addChildAt(vedo, i);
    // register whatever listener you like with the vedo here
}

Then the setter method should be polymorphically called. You may have to pass the entire public DisplayObject interface through the VisibilityEnabledDisplayObject decorator, I can't remember right now...

Dustman
The thing is I want to listen to events on an already existing object in a loaded swf. So I'm afraid that won't be possible.
Leeron
+1  A: 

See http://stackoverflow.com/questions/210666/can-an-actionscript-component-listen-to-its-own-propertychange-events

It says yes.

If you use the [Bindable] tag without specifying an event type, then when the property changes its value, an event of type: PropertyChangeEvent.PROPERTY_CHANGE, which is the string 'propertyChange', will be dispatched.

Therefore, to be able to register to listen to that event, you need to say:

this.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onOnChange);

The reason why your listener function was never called is that the event type was not correct.

Note that the listener method will be called when any of the variables marked as Bindable in your class changes, not only 'on'. This event comes with a property called 'property' that indicates which variable was changed.

To avoid being called on each Bindable variable, you need to specify an event in the [Bindable] tag:

[Bindable(event="myOnChangeEvent")]

and dispatch that event manually when you consider that the property is changing (ie: in the setter), though that didn't seem to be what you wanted to do.

Todd Moses
The thing is I want to listen for events on an already existing object in a loaded swf. So I'm afraid that won't be possible
Leeron
+1  A: 

Create a mediator class, that will manipulate your display object. through instance of that class you can set and get any properties and monitor changes. for example

public class ExistingDOMediator extends EventDispatcher{
   protected var _view:DisplayObject;
   public function ExistingDOMediator(view:DisplayObject):void{
      super();
      this._view = view;
   }
   public function get visible(value:Boolean):void{
      return this._view.visible;
   }
   public function set visible(value:Boolean):void{
      if(this._view.visible!=value){
         this._view.visible = value;
         this.dispatchEvent(new Event('visibilityChanged'));
      }
   }
}
a_w