Header text

EssayTagger is a web-based tool to help teachers grade essays faster.
But it is not an auto-grader.

This blog will cover EssayTagger's latest feature updates as well as musings on
education, policy, innovation, and preserving teachers' sanity.

Saturday, September 10, 2011

BitmapButton: A custom-skinnable ActionScript button

Source code for a simple, skinnable ActionScript button class that includes a really handy arbitrary data field.

Now that I'm a whole 20 days into learning how to code in Flash's ActionScript language, I'm getting pretty dang good.

Yesterday I needed to create a button for the Flash grading app, but I didn't want to use the default fl.controls.Button class that resembles standard HTML form buttons.

I wanted to be able to skin the button with my own Bitmaps that I would generate in Flash. I figured that the easiest way to do this would be to build my own custom button class. So I did:

It's pretty straightforward. It takes two Bitmaps as inputs to its constructor, one for the default button state and one for the onHover (aka MouseOver) state.

The key feature for me is that I designed this button class to store any arbitrary data Object that you want to stuff into it. Why is this important? Well, chances are that when the user clicks a button, you want the app to do something as a result. The event handling system will tell you which button was clicked, but normally that's it. The arbitrary data field allows us to get the button and its associated data Object at the same time.

Let's look at the BitmapButton in action:

Pretty simple. Create a new BitmapButton and pass in the Bitmaps for the two button states. Then we stuff in our data Object. Add it to the parent object and then wire it up to trigger an onClick handler that we specify in the parent code.

The onClick handler is also simple:

(Note: the "SomeDataType" should obviously be changed to match the data type of whatever you stuffed in there)

Here we see that we can regain access to the exact BitmapButton instance that triggered the onClick handler. And once we get the BitmapButton instance, we have access to its data field!


This is all super-simple, but as a newbie to ActionScript it took me a while to get to this level of understanding of how all the pieces fit together. I relied on a lot of google searches to get this far and there seemed to be a lot of confusion out there about event handling and getting custom data out of events. Well, here's killing two birds with one stone.

Additional design notes about the BitmapButton class:
--The BitmapButton constructor takes Bitmaps because that it leaves the door open to reuse the Bitmap's underlying BitmapData with other BitmapButton instances. This is important because the BitmapData is what eats up memory space; a single BitmapData image can be reused over and over again by different Bitmap objects without (much of) an additional memory hit. I'll be using this "add comment" button over and over again all over my grading app's interface. Best to plan for efficiency now.

--You'll notice that the BitmapButton handles its own MouseOver and MouseOut state changes. This allows the code that creates the BitmapButton to "set it and forget it"--the button manages itself as much as possible.

--However, the onClick is wired up by the parent that creates the BitmapButton. I did it this way so that each BitmapButton instance can be wired to trigger different handlers that live in all sorts of different places. There really wouldn't be much for the BitmapButton to do in its own onClick anyway. The most it could do would be to call dispatchEvent() to notify a listener that it was clicked.

--If you do need more custom actions in the BitmapButton or in its MouseOver/MouseOut handlers, you can create your own customized class that extends BitmapButton and overrides the MouseOver and MouseOut handlers.

Full sample source code for using the BitmapButton class:

Note: Minor code details have been left out of the code--most significantly the "package" declaration that would normally surround the import statements and the class declaration. I'm assuming that you're already comfortable working with packages and separate class files.