Thursday, April 2, 2009

Flash bugs: dynamic SimpleButton gotcha

I'm creating a SimpleButton in ActionScript and it ain't showing up.

var b:flash.display.SimpleButton = new flash.display.SimpleButton();
b.upState = bla;
b.overState = bla;
b.downState = bla;
b.hitTestState = bla;
b.useHandCursor = true;
this.addChild(b);

The problem is, the button, she no appear. Nada.

I thought maybe my problem is that I'm using the same sprite for the different states, but changing that didn't make any difference.

Turns out, Flash is proving its inferiority once again.

The SimpleButton constructor, it so happens, accepts four OPTIONAL arguments, being the four SimpleButton states.

Given that they are OPTIONAL, you would think you could omit them ALL and just set the four state properties after construction.

You'd think so. And so did I.

But it turns out that, even though the documentation and the in-editor code helps all say the states are optional, THE UP STATE IS ACTUALLY MANDATORY.

Ridiculous.

In short, this works, because it supplies the mandatory-though-pretending-to-be-optional UpState argument to the SimpleButton constructor :

var b:flash.display.SimpleButton = new flash.display.SimpleButton(bla);
/*b.upState = bla; - no longer needed*/
b.overState = bla;
b.downState = bla;
b.hitTestState = bla;
b.useHandCursor = true;
this.addChild(b);

And of course, you might prefer to just save lines and go :

var b:flash.display.SimpleButton = new flash.display.SimpleButton(bla, bla, bla, bla);
b.useHandCursor = true;
this.addChild(b);




On a related note, I was trying to figure out WHY Flash is so STUPID in this regard. (Stupidity and unintuitive behaviour are more common than I would have expected in ActionScript. I really honestly thought Microsoft's XAML was passable and that Adobe would be as good or better. Sadly, Adobe is actually far behind M$ in the 'we make things that actually make sense' game, even if M$ itself isn't perfect.)

My first guess was that the constructor determines the SimpleButton's dimensions from the upState, and thus, when no upState is passed to the constructor, the SimpleButton has no idea how big it needs to be.

If that were the case, I could simply set the SimpleButton's width and height, and it would work.

But no go.

Here's the code :

var b:flash.display.SimpleButton = new flash.display.SimpleButton();
b.width = 100;
b.height = 100;
b.upState = bla;
b.overState = bla;
b.downState = bla;
b.hitTestState = bla;
b.useHandCursor = true;
this.addChild(b);

And it is as dead and useless as the very first code listing in this article.

In short, it seems that the SimpleButton is COMPLETELY UNABLE TO HANDLE UPSTATE BEING OMITTED FROM THE CONSTRUCTOR INVOCATION.

Which makes me ask why Adobe's documentation is so poor that there is no comment about it. And why their compiler doesn't complain when that argument is missing from the constructor invocation. And in fact why, overall, they make such an unintuitive design.

Here's what I would have done, since I believe in making APIs as flexible as possible :

1) All constructor arguments are optional.

2) Button width and height are calculated just-in-time, or at least, calculation is deferred until upState gets set for the first time on a given SimpleButton instance.

Voila! Talk about intuitive! In contrast, I really don't know how Adobe muck up like this, and at multiple places throughout their API. Shame, Adobe. Shame. Please lift your game.

No comments: