AS3 Simple Button: breaking all rules

I found something funny the other day when inspecting Flash Player’s built-in SimpleButton, a standard member of the display list. Or I thought it was standard.

SimpleButton isn’t a DisplayObjectContainer, so it doesn’t have methods like addChild() and getChild(). Instead it has convenient button states, such as the upState property, that contain children in a different way than DisplayObjectContainer. Which made me pause.

DisplayObject.parent is typed as a DisplayObjectContainer, both in the documentation and when analyzing the class through describeType() (reflection). So what is the value of the parent property when a display object is added to a SimpleButton? It’s the SimpleButton instance, a non-DisplayObjectContainer! Test all day long if you like, the parent property is very clearly typed to the container but just as clearly returning a different type. I now relinquish all claim to understanding the Flash Player and how it works.

3 thoughts on “AS3 Simple Button: breaking all rules

  1. The reason you’re getting a little funkiness is that the SimpleButton is really an AS3 implementation of the Button class from AS1/AS2. Child objects in SimpleButton are created in Flash Authoring, and are not meant to be dynamically instantiated or manipulated, which is the most likely reason that SimpleButton does not extend DisplayObjectContainer. A SimpleButton is actually a four-frame “MovieClip” object with a fixed number of frames. It’s one of the few quirky holdovers from the quirky legacy programming days of AS2.

    In AS2, the Button class was really treated as a MovieClip by the Flash Player (AVM1), even though there was no MovieClip API support. You could simulate a custom Button with very little effort by creating a MovieClip and designating three frames by their “magic frame labels”: “_up”, “_over”, “_down” and the hit state by setting “this._hitArea = this.hit_mc;” on the first frame of the clip. Create a button event for the MovieClip, and it would magically act just like a Button.

    This functionality was carried over into AS3, (see the MovieClip.ButtonMode property), which makes me think that SimpleButton is treated like a specialized MovieClip by the Flash Player, without access to the MovieClip API.

    Try this:
    1. Create an MC with three frames, labelled “_up”, “_over”, “_down”.
    2. Create another layer with a stop() action across all three frames.
    3. Add this code to the main timeline:
    btn_mc.buttonMode = true;
    btn_mc.addEventListener(MouseEvent.MOUSE_DOWN, onBtnPress);
    function onBtnPress(evt:MouseEvent):void { trace(“Button Pressed!”); }

    And you have effectively demonstrated that a SimpleButton is in fact a MovieClip, but without access to the MovieClip API. Without access to that API, SimpleButton effectively extends InteractiveObject, which is why you get the funky results on child objects.

  2. Tyler, that _is_ crazy. You just blew my mind.

    So, in the upState, for example, the following code…

    `this.parent as DisplayObjectContainer`

    would evaulate to null? WTF, how is that possible?

    Joe: interesting and informative as your comment is, it doesn’t really address Tyler’s point that a SimpleButton contains DisplayObjects, but also can’t possibly, because of it not being a DisplayObjectContainer. MovieClip is a DisplayObjectContainer, but SimpleButton is _not_ a MovieClip. Not these days anyway.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>