ActionScript.org Flash, Flex and ActionScript Resources - http://www.actionscript.org/resources
AS3 Dropdown Menu with Reusable Classes
http://www.actionscript.org/resources/articles/979/1/AS3-Dropdown-Menu-with-Reusable-Classes/Page1.html
Jody Hall
My interest in Flash started mostly because of a Jib-Jab cartoon ("This Land") in 2004. I'm the author of a feature I call "Mazoons," which are a combination of mazes and cartoons. In 2002, I even had a book published, "Super Silly Mazes." I'm not a professional programmer, but making my mazes interactive by programming them with Flash became a hobby/obsession of mine, to the point where I have now learned more than I bargained for. Lately I'm working on a new website about Flash and Actionscript 3.0 called The Flash Connection
By Jody Hall
Published on February 18, 2010
 
In this article, you will learn how to make your own reusable classes that will enable you to add custom dropdown menus to your Flash projects. You will be able to make the menu and the buttons any size or color you want, using the font of your choice, just by sending the class the information it needs to construct it for you. Best of all, learning the techniques used to put this together will help increase your skills at making custom classes in general, as you start thinking more in terms of "programming for programmers."

Planning and Visualizing the Project
Hi! Welcome back to my never-ending series (hopefully) on making your own custom reusable Actionscript 3.0 classes. This time I'm going to share with you how to make a custom dropdown menu class. We'll also make an associated button class to represent the items that the dropdown menu is going to use. I'll share with you the planning and the thinking that goes into creating something like this, as we build it together starting with just the idea. If you are primarily a designer, or a visual person, that's okay, too. You will see that it helps to be able to draw and/or visualize the thing you are trying to make, even though you are doing it with strictly code.

Visualizing the finished menu beforehand
So we start with a drawing or a visualization of the object or objects we are going to make with code and classes. Right up front, if I draw a picture or a diagram of the overall thing I want to make (or if I even just have a mental picture), it helps me tremendously when I set out to write the code. This kind of planning is important, and you've no doubt heard that you should never just start cranking out code without doing some kind of planning. It's true. And along with the diagram or mental picture, you will also want to start determining what constitutes a class in your diagram, and then you can start listing what things you expect each class to do. Peoples' preferences vary, and I'm probably "old-school" in that I like to keep a scratch pad and pen next to the computer, and make an actual drawing. But if you'd rather draw using software, that's great too, and I'm actually making my illustrations for this tutorial using Flash.

For example, if I drew a diagram of the dropdown menu, it would probably look something like this:

You can see that the menu will have several parts. The "heading" will be a single button, and the "panel" (the part that goes up and down) will be a stack of buttons. Both the heading and the panel will use the same kind of button, and all of these buttons will be instances of the MenuButton class. You can see that MenuButton itself will be composed of other parts. An instance of the Shape class will serve for a background, and a dynamic textfield will be in the foreground. The next drawing illustrates the action of the dropdown menu, along with some helpful visualization of x and y coordinates that are going to be necessary for positioning. Also, the finished dropdown menu is going to need a masked area to serve as a view window through which the panel will "peek through" as it moves up and down:

This kind of drawing and planning (and thus, visualizing) is indispensable to your coding, so whatever you are making, you won't want to skip this step. But like I said, these images can also be mental, too. Just make sure you have some kind of concept of how your objects are going to be composed, and you'll be much better off when you write the code. Otherwise you will tend to have to revise things a lot, and as you change your mind about this and that, you will tend to forget what parts you left in or took out in the process.

In the above drawing, the dashed lines represent the panel opened, and the panel closed, and the (x, y) positioning that will need to be done can be fairly easily determined. Also the idea that we will need a masked area is shown, and we also get a good concept of the layering of the objects. The various parts will become properties in the finished class. Also at this point, it can be decided just what action will open and close the menu. So we decide that the menu will open when the mouse rolls over the heading, and the menu will close when the mouse rolls out of the whole thing. The menu will open and close by tweening, and we will employ some tweening classes for that. We will come back to this drawing later when we make the DropMenu class. For now, just realize that having these two drawings gives us an overall road map of where we need to go to make this dropdown menu a reality.

What will we require of MenuButton?
The other thing to do besides making drawings is to start asking questions and listing requirements. So let's start with the MenuButton class. The questions to start asking are many, but they all pertain to what is going to be expected from this class by outside code. What sorts of things do we need to send it, what sorts of things are we going to get back (if anything), what sorts of things can be customized from the outside controlling code? In fact, forget for a moment that this is going to be used in a dropdown menu, and consider it separately. If this were just a generic button (and it really is, after all), what do I want to be able to do to customize it?

When I start answering those questions for the MenuButton class, a bunch of things start occurring to me, especially looking at the first drawing and focusing on how the button itself will be composed. It occurs to me that the whole "button" ought to be a Sprite object, because it won't need a timeline, but it does need interactivity (mouse events), and it needs to contain other objects. There is a background shape, so I would like first of all to be able to control the color of it, and also the size (width and height, naturally). There is a foreground dynamic textbox, so it should go without saying that I need to be able to set the text (label). Along with that, I would also like to be able to control the font, the font size, and the font color. The textfield needs to be always centered horizontally and vertically, and autoSize from the center. And finally, just in case I might want to use a font other than a device font (like some obscure font I have that I like, but I know my end users are maybe not likely to have), I should be able to designate whether to use embedded fonts or not.

This is a pretty good list already:
  • Our class will extend Sprite, so it can contain the other objects
  • It will need (at least) these properties:
  • A label property so we can set the text (String)
  • A fontName property so we can set the font (String)
  • a fontSize property so we can set the font size (int)
  • a fontColor property so we can set the font color (uint, a hex number)
  • an embedFonts property so we can decide to embed fonts or not (Boolean)
  • a backgroundColor property so we can set the background color (uint, a hex number)
  • a width property so we can set the width of the button (Number)
  • a height property so we can set the height of the button (Number)
For those last two, since Sprites already have a width and height property, we will need to override those and substitute our own. Also, for all of these various properties, I would like the flexibility to be able to set all of the properties in the constructor if I want, but also be able to decide not to. I should be able to create a new instance of the class with no parameters passed, and get some kind of default button, with a hand cursor, and be able to further customize it by setting my eight properties separately if I want. In other words, you have to always be thinking about how this class will be used from outside of it, and make it as versatile, useful, and customizable as you possibly can.

What will we require of DropMenu?
Similarly, the DropMenu class has its own list of questions and requirements that need to be thought through. How are we going to set the heading for the menu? How are we going to add items to the panel? And how are we going to accomplish the motion of the panel? As I perceive it from the drawing, the class will need:
  • a heading property (to set the heading)
  • an addItem method (to add items to the dropdown panel from outside the class)
  • some way to tween the panel up and down
  • mouse event handlers added to the heading to make the panel go up and down
The DropMenu class should also allow me to make an instance of it without sending it any arguments to the constructor, for convenience, but if I want to, I should be able to send the constructor a Sprite instance to be used for the heading.

Programming for other programmers
In fact, it's helpful to pretend you are making your class for some other programmer to use who doesn't know anything about it. To keep the learning curve as short as possible, use descriptive and memorable property names and method names. Don't make required parameters unless you absolutely must. Make separate "setter" functions for all the parameters, so that they can optionally be set separately after the class is instantiated. Think about the built-in classes and just how you already use many of those. Realize that you use them and almost never get to see their insides, you just learn their API's from the documentation (an API, or "application programming interface," in the case of classes, is simply the list of public methods the class makes available, and what parameters those methods are expecting. Methods are simply functions that belong to a class, so the words method and function are usually interchangeable in this article). Some API's are easy to learn, and others require researching their documentation frequently. And that's how you should try to make your own classes: as much like the ones that come with Flash as possible, and as easy to learn as possible, especially without peeking inside of them.

This will make it a much easier for yourself also, when you have to come back to your own classes later. It might take longer to carefully craft a well thought out class, but in the long run you are putting some gems in your class library for later reuse, rather than a hacking something together quickly that gets the present job done, but doesn't have much in the way of future re-usability.

Having outlined those requirements for the whole project, and having figured out what we expect from the MenuButton and DropMenu classes, on the next page we will start coding the MenuButton class.

Creating the MenuButton Class
Having now outlined the project, let's jump in and start creating it. Open Flash, select File / New... and create a new Flash file (Actionscript 3.0). Immediately save it. In the process of saving it, create a new folder. I called mine Dropdown_Menu_AS3 (if you prefer, you can also get the completed files from the downloadable ZIP file at the bottom of the last page of this article). I saved the fla file within this folder and named it dropdown_menu_test.fla.

Now go to File / New... and choose New Actionscript (AS) file. Type in (or copy and paste) the following basic class outline:
[as]package {
    import flash.display.*;
    import flash.events.*;
   
    public class MenuButton extends Sprite {
   
        public function MenuButton() {
           
        }
    }
}[/as]
Immediately save this file to the same folder location as the fla file. You may have to browse your system's folder tree again to get there, as Flash seems to remember the last location of fla and as files separately (sometimes I wish it didn't!). But once you've saved a file of each kind there, you're good to go after that. The only thing to note here is that our class extends the Sprite class. As such, it inherits from the DisplayObjectContainer class, so it can contain other objects. In fact, the Sprite class is like the MovieClip class, without all the timeline methods and properties like gotoAndPlay, currentFrame, etc. All of those things are excess baggage if you know for a fact you won't be using them, and we won't be in this case. We won't be linking to a library symbol--this class will draw its own graphics using code. We do get all of the other properties of MovieClips though, like x, y, rotation, width, height, alpha, and a host of others, so you are still on familiar ground if you did a lot of AS2. It's not that different at its heart.

Let's get something displaying on the screen
What I like to do right off the bat is to get something on the screen I can see immediately. I like visual feedback a lot--I like to see what I'm building as I go along. So in the fla file, let's write these two lines on frame 1 of the main timeline:
[as]var btn:MenuButton = new MenuButton();
addChild(btn);[/as]
Before we test this, though, let's do a little more work on the class, so that it produces something we can see. I do already know that the MenuButton class is going to have a draw() method, as I have a scheme already in mind where whenever I update a property, I can just immediately call the draw() method so that the button will redraw and update itself. But for now, the draw() method will just create the background shape we discussed earlier, and add it to the display list. Also, let's go ahead and set buttonMode to true (for the hand cursor to show up). Also, I already know ahead of time that I am going to want to set mouseChildren = false, because later there will be a dynamic textbox in the mix, and if you don't set mouseChildren to false, the hand cursor won't show over the textbox. Setting these two properties is something you just get used to doing when you make Sprite buttons with dynamic text boxes for their labels. So here's the revised class that sets those two properties I just mentioned in the constructor function, and also calls a brand new freshly written draw() method that just draws a rectangle shape and adds it to the display:
[as]package {
    import flash.display.*;
    import flash.events.*;
   
    public class MenuButton extends Sprite {
   
        public function MenuButton() {
            buttonMode = true;
            mouseChildren = false;
            draw();
        }
        private function draw():void {
            //background shape:
            var bg:Shape = new Shape();
            bg.graphics.beginFill(0xFFCC00);
            bg.graphics.drawRect(0, 0, 150, 30);
            bg.graphics.endFill();
            addChild(bg);
        }
    }
}[/as]
In the above, just to get something I can see and run immediately, I have hard-coded some of the values that will later get replaced with dynamic variables instead, like the width and height of the rectangle that is drawn, and its color. Save the class file (Ctrl-S), test the movie (Ctrl-ENTER), and you should see a rectangle in the upper left hand corner of the screen that gives you a hand cursor when you hover it with your mouse. We've got a long way to go, but it's a cool beginning. We know that our class is being instantiated (that means a new instance is being made, or constructed), and we are getting mouse feedback from it.

A brief aside about classes (for those new to them)
Classes are an absolutely fantastic way to write code if you want to make a template for some kind of object and stamp out a LOT of copies, or if you just want to encapsulate a self-contained block of code. If you are at all shaky about what classes are or what they can do, try this short experiment. In the fla file, let's make more instances of the class we just made. You will need to modify the y value of each one so that they are not stacked up on each other, but you will see how easy it is to make more instances with just a few lines of code. Change the code on frame 1 of the fla file so that it says:
[as]var btn:MenuButton = new MenuButton();
addChild(btn);
var btn2:MenuButton = new MenuButton();
addChild(btn2);
var btn3:MenuButton = new MenuButton();
addChild(btn3);

btn2.y = 40;
btn3.y = 80;[/as]
Now you can see that there are three instances of our class created and displayed to the screen. Each one has its own copy of the constructor function, and each one has its own copy of the draw() method so that it can draw a rectangle to the screen (which it did). The instances of the class are called objects, and they all occupy their own space in your computer's memory, and they are each a separate little bundle of all the properties and methods that we have written into the class file, but also all the ones that they've inherited from the Sprite class. Case in point: each one got an inherited y property that we were able to set, so that they could be spread out on the display and not stack up visually. Another case in point: each one got its own copy of the buttonMode property so that we could set it to true and get a hand cursor. Each one remembers not only its own property names, but whatever value was last set for each property. You could have just as easily set buttonMode = false for one of those if you wanted, for example. So you can see the power of extending classes. We get all the existing properties and methods of the Sprite class to manipulate at will, and we get to choose to add whatever custom ones of our own we want! Also, with just one class file, we can crank out as many copies as we want, and manipulate the properties and methods of each one independently of the others. From just ONE class file, comes however many copies (objects) we care to create!

The constructor of a class is the special function with the same name as the class, and it is always designated public. This function runs when outside code uses the new keyword to make a new instance of the class. So the constructor is the place to put initialization code, because it conveniently only runs once, when an object is created (or instantiated) from the outside, or controlling code. Other public functions can be called repeatedly from the outside after the object is made, but the constructor just runs once for each object created from a class.

Now that we're all on the same page...
This ability to crank out as many copies of the same class as we want will come in very handy. Each "copy" (object, or instance) of the MenuButton class will thus be able to be configured with a text label, so that it can display text of its own. Later, each one can have a different background color if we want, each one can be a different size, have a different font, and all the things I talked about on the previous page. Once you understand the basic, fairly simple concept of classes and objects, you are well along to putting it all to good use, because the more complex stuff isn't really so complex after all. What looks complex is sometimes just a bunch of simple stuff connected together!

Let's move ahead and start adding the properties I mentioned on the last page. Now, by convention, private properties in a class are sometimes preceded with an underscore (at the whim of the programmer, but like most conventions, it's a good one), and we're going to be using a lot of "setter" functions in this class, and that's when the use of underscores becomes really valuable. I'll explain the use of "setter" functions later on, but for now, let's just add all those private variables to a variables list in the class. I gave a lot of thought to what I might want for default values, as well. So the constructor function has a parameter list with eight items (which is really long!) but none of them is required because they all have default values. Then I reasoned what would be the most natural ordering of all of these parameters. Anyway, here is what I came up with:
[as]package {
    import flash.display.*;
    import flash.events.*;
   
    public class MenuButton extends Sprite {
        private var _label:String;
        private var _fontName:String;
        private var _fontSize:int;
        private var _fontColor:uint;
        private var _embedFonts:Boolean;
        private var _bgColor:uint;
        private var _width:Number;
        private var _height:Number;

        public function MenuButton(label:String = "Click Here",
                                   fontName:String = "Arial",
                                   fontSize:int = 14,
                                   fontColor:uint = 0x000000,
                                   embedFonts:Boolean = false,
                                   bgColor:uint = 0xFFCC00,
                                   width:Number = 150,
                                   height:Number = 30) {
            _label = label;
            _fontName = fontName;
            _fontSize = fontSize;
            _fontColor = fontColor;
            _embedFonts = embedFonts;
            _bgColor = bgColor;
            _width = width;
            _height = height;

            buttonMode = true;
            mouseChildren = false;
           
            draw();
        }
        private function draw():void {
            //background shape:
            var bg:Shape = new Shape();
            bg.graphics.beginFill(0xFFCC00);
            bg.graphics.drawRect(0, 0, 150, 30);
            bg.graphics.endFill();
            addChild(bg);
        }
    }
}[/as]
That may seem like a lot to take in. But really it's just a matter of declaring eight private variables, all with underscores in front of them. In the constructor all eight of them are given values straight from the parameters list. Each parameter in the list has a default value after the equals sign. The ability to put an equals sign and a value after it in your parameters list is really cool, because it allows you to make optional parameters that the user of the class can either supply, or not. If no arguments are supplied, the default values are used instead. So here's how it works: when outside code makes a new instance of our class, if no arguments are supplied to the constructor, as in:
[as]var btn:MenuButton = new MenuButton();[/as]
Then what will be constructed is a button that says "Click Here" on its face, in an Arial font, size 14, with black text, no embedded fonts, a background color of orange, a width of 150 and a height of 30. However, someone might also supply just a first argument, like so:
[as]var btn:MenuButton = new MenuButton("My first menu button");[/as]
In this case, what they get is a button with different text than "Click Here" (which was the default), but with all the remaining parameters still using the default. That's why I put some thought into the order, to make it as natural as possible. If someone wants to supply the fourth argument, for example, then they are also stuck with supplying the first three.

Of course, all of this doesn't work just yet, we still have yet to program it all. Right now if you test the movie, the class will do exactly what it was already doing, as we haven't affected the behavior at all with these changes. We just simply made a list of eight parameters, recorded them into private variables, made them all optional (because they all have default values), and now we have to make something happen within the class body for each of them. Since there is yet a bit of work to be done, we will take it up in earnest on the next page. However, we have a crystal clear idea of where we want to take this, and it won't be so very difficult. And at the end of the next page, we will be able to test the finished MenuButton class and make it crank out some customized buttons!


Further refining the MenuButton class
What we will accomplish on this page is to use the information passed in from to constructor to vastly improve the draw() method. The goals are fairly clear, and I outlined them already (we want to be able to customize stuff from the outside). I would just like to add that because of the way the display list works, things that are added to the display with addChild() are added in front of everything that's already there. Because of this, we need to draw things to the display and add them from the back to the front, like an artist painting a picture by starting with the background, and then adding in the foreground on top of what's there. In this case, there are only two things to be concerned with, the TextField for the label (which we haven't created yet) and the background shape. We'll also put in some code that will "erase" everything that's there (more about that later, though).

Modifying the draw() method:
For starters, let's modify the code that draws the background so that it uses the private variables instead of the hard-coded numbers we used before. For clarity, here's the current draw function just by itself:
        [as]private function draw():void {
            //background shape:
            var bg:Shape = new Shape();
            bg.graphics.beginFill(0xFFCC00);
            bg.graphics.drawRect(0, 0, 150, 30);
            bg.graphics.endFill();
            addChild(bg);
        }[/as]
Change the fourth and fifth lines there to these:
[as]bg.graphics.beginFill(_bgColor);
bg.graphics.drawRect(0, 0, _width, _height);[/as]
That takes care of the background, now all we have to do is create a TextField. But first, let's create an instance of the TextFormat class so that we can style the font's size and color:
            [as]var tFormat:TextFormat = new TextFormat();
            tFormat.font = _fontName;
            tFormat.size = _fontSize;
            tFormat.color = _fontColor;[/as]
Again, the values supplied here are the private properties that were recorded from the constructor's parameter list. We're just passing them along to the TextFormat object. However, now that we are using a class that wasn't imported, it's going to be necessary to add this line to the list of imports:
[as]import flash.text.*;[/as]
Next, we'll create a TextField instance, and keep using those private variables to customize it:
            [as]var tField:TextField = new TextField();
            tField.multiline = false;
            tField.selectable = false;
            tField.embedFonts = _embedFonts;
            tField.defaultTextFormat = tFormat;
            tField.autoSize = TextFieldAutoSize.CENTER;
            tField.antiAliasType = AntiAliasType.ADVANCED;
            tField.text = _label;
            tField.x = _width / 2 - tField.width / 2;
            tField.y = _height / 2 - tField.height / 2;
            addChild(tField);[/as]
We start off creating a new TextField instance called tField. Set multiline to false because all we need is one line. Selectable should be set to false because we are making a button, nobody is going to need to copy and paste our button's label. Standard stuff so far. The value for tField's embedFonts variable can be true or false. We just pass along the value that's in our private _embedFonts variable, whatever it is, because it will likewise contain either true or false itself. We set tField's defaultTextFormat property to the TextFormat object we previously made. Next, set the autoSize property to "center," and antiAliasType to "advanced."

(Using the constants TextFieldAutoSize.CENTER and AntiAliasType.ADVANCED is pretty typical here. If this is new to you, here's a a quick explanation: There are a zillion constants written into the built-in classes. Some classes are nothing more than just a collection of these. They are nothing mysterious at all, they are just public static variables that contain strings. When something is public static, you access it by using the name of the class with a dot. A familiar example would be MouseEvent.CLICK, which is a public static variable that just simply contains the string "click." Try tracing it out sometime and see for yourself).

Another brief aside you can skip if you already know it:
Helpful hint: think of the word static as meaning "only one copy." No matter how many instances are made from a class, if a property (variable) or method (function) of a class is static, there will only ever be one copy of it, which belongs to the class, and not to each instance of the class, and it is accessed by using the name of the class (an initial capital letter is usually your clue / giveaway) and a dot, instead of the name of any instance. You can make your own static items, too, but we won't be doing any of that for this project.

Next, the tField's text property is set to the private _label variable. Once again, the value here came down from the constructor function, so it will either contain "Click Here" if no argument was supplied, or it will contain whatever string of text was supplied for a first argument. The next two lines take the tField, which now has text in it, and center it both horizontally and vertically. Since the text has been added to it now, in the default font size and color, and it's been set to autoSize itself, it should now have a height and width of its own that can be used to center it. The _width and _height private variables are used for centering, instead of the built-in width and height properties inherited from the Sprite class. Now that the background shape has been drawn, really either one could be used, but it seemed more natural to me to keep using the supplied values. The centering code is typical and pretty easy to figure out. The tField's x property is set to the _width / 2 (which gives you the center of the whole button) minus the tField's width / 2. Even though the tField was set to autoSize from the center, the "registration point" of the tField is still considered to be in its the upper left hand corner.

Centering in the y direction is done exactly the same way, and finally the tField object is added to the display list with addChild(). One thing remains to be done and our draw() method will be complete. We'll add some code to the beginning of it that will remove everything from the display list if anything is there:
            [as]while(this.numChildren > 0) {
                this.removeChildAt(0);
            }[/as]
If there is nothing on the display list of this button (which will be the case the first time it is called), this while loop won't run at all. However, if the background shape and the text field have been previously created and added to the display list, this will see that they are removed just before they are created and added again. In this way, the whole button definitely refreshes itself every time, and everything is added from the back to the front again.

Creating "setter" functions:
Our final chore, before this class is complete, is to add eight "setter" functions so that the private variables in the class can be assigned new values at any time from the outside. If you haven't seen setter functions in action before, an explanation is in order. If you have, you can safely skip the following explanation. I have covered this before in my previous tutorials, but just in case you missed it, here goes. A "setter" function uses the set keyword along with a name of your choice, to create a function that from outside the class can be treated as though it were a property. Remember that in authoring classes we are always concerned with how instances of the class will be manipulated from the outside. Here is our first setter function:
        [as]public function set label(value:String):void {
            _label = value;
            draw();
        }[/as]
Setter functions must be public, otherwise they wouldn't make any sense. With the above setter function in place, from the outside code, a call to this function might look like this:
[as]btn.label = "This is my first button";[/as]
(Notice that from the outside, the word "label" is used without an underscore. This is the reason underscores are so handy for private class variables, because when using setter functions, the two names must be different inside the class).

When this command is encountered, Actionscript does us a huge favor: It finds our setter function in the class, and calls it, passing in the string of text after the equals sign ("This is my first button") as an argument to the parameter list. The parameter list for a setter function can only be one item long, so it all works out well. The "value" parameter is (magically) assigned the string of text. Next, in the body of the function, our _label (private variable) receives it, and the whole button is redrawn by calling the draw() method again. The draw() method removes everything from the display list, remember, and draws it all over again. Only this time it's redrawing it with a new string of text contained in the _label variable!

Anyway, that's the scoop on setter functions. They are methods (functions), but from the outside, they can be treated like properties, complete with dot syntax. Similarly, there are "getter" functions, but they do the opposite. They don't take any parameters, they return a value (but only one!), and from the outside code, they can be treated like properties using dot syntax. However, this class won't need any getter functions, so I just mention them in passing.

Overriding existing methods of the Sprite class:
So, we'll write similar setter functions for all of the private properties. But we still have one more thing to cover: the public override of the width and height properties. We can safely override these properties, and supply our own, because we won't be needing the original ones, ever. In case you didn't guess, the built-in classes pretty much always use getters and setters. So what we are really overriding is the public method set width(), like so:
       [as] public override function set width(value:Number):void {
            _width = value;
            draw();
        }[/as]
Other than the override, this is exactly the same as all the other setters. And the override for height works exactly the same way. Also, each and every setter is going to call the draw() method, so that the button is updated each and every time a property is set. Here is the complete, finished class:
[as]package {
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;

    public class MenuButton extends Sprite {
        private var _label:String;
        private var _fontName:String;
        private var _fontSize:int;
        private var _fontColor:uint;
        private var _embedFonts:Boolean;
        private var _bgColor:uint;
        private var _width:Number;
        private var _height:Number;

        public function MenuButton(label:String = "Click Here",
                                   fontName:String = "Arial",
                                   fontSize:int = 14,
                                   fontColor:uint = 0x000000,
                                   embedFonts:Boolean = false,
                                   bgColor:uint = 0xFFCC00,
                                   width:Number = 150,
                                   height:Number = 30) {
            _label = label;
            _fontName = fontName;
            _fontSize = fontSize;
            _fontColor = fontColor;
            _embedFonts = embedFonts;
            _bgColor = bgColor;
            _width = width;
            _height = height;
           
            buttonMode = true;
            mouseChildren = false;

            draw();
        }
        public function draw() {
            //first remove any existing elements, if any:
            while(this.numChildren > 0) {
                this.removeChildAt(0);
            }
            //background shape:
            var bg:Shape = new Shape();
            bg.graphics.beginFill(_bgColor);
            bg.graphics.drawRect(0, 0, _width, _height);
            bg.graphics.endFill();
            addChild(bg);
            //text format:
            var tFormat:TextFormat = new TextFormat();
            tFormat.font = _fontName;
            tFormat.size = _fontSize;
            tFormat.color = _fontColor;
            //text box:
            var tField:TextField = new TextField();
            tField.multiline = false;
            tField.selectable = false;
            tField.embedFonts = _embedFonts;
            tField.defaultTextFormat = tFormat;
            tField.autoSize = TextFieldAutoSize.CENTER;
            tField.antiAliasType = AntiAliasType.ADVANCED;
            tField.text = _label;
            tField.x = _width / 2 - tField.width / 2;
            tField.y = _height / 2 - tField.height / 2;
            addChild(tField);
        }
        public function set label(value:String):void {
            _label = value;
            draw();
        }
        public function set fontName(value:String):void {
            _fontName = value;
            draw();
        }
        public function set fontSize(value:int):void {
            _fontSize = value;
            draw();
        }
        public function set fontColor(value:uint):void {
            _fontColor = value;
            draw();
        }
        public function set embedFonts(value:Boolean):void {
            _embedFonts = value;
            draw();
        }
        public function set backgroundColor(value:uint):void {
            _bgColor = value;
            draw();
        }
        public override function set width(value:Number):void {
            _width = value;
            draw();
        }
        public override function set height(value:Number):void {
            _height = value;
            draw();
        }
    }
}[/as]

It may seem like a lot of work that we had to do just to get a basic button going. But now when we test drive this, we can do awesomely cool stuff like this (try this in your fla file):
[as]var btn:MenuButton = new MenuButton("Hey, this is cool!");
btn.width = 200;
btn.height = 50;
btn.fontName = "Comic Sans MS";
btn.fontSize = 18;
btn.backgroundColor = 0x0000FF; //blue
btn.fontColor = 0xFFFFFF; //white

addChild(btn);[/as]
But, what about rollovers?
You might say, yeah, but this is just a plain button, and I like rollover effects and stuff. Well, don't forget that we can affect all those properties from outside the class, even in response to events. As a demonstration, try adding this code to the above and check it out!
[as]btn.addEventListener(MouseEvent.ROLL_OVER, over);
btn.addEventListener(MouseEvent.ROLL_OUT, out);

function over(event:MouseEvent):void {
   MenuButton(event.currentTarget).backgroundColor = 0xFF0000; //change to red
}
function out(event:MouseEvent):void {
   MenuButton(event.currentTarget).backgroundColor = 0x0000FF; //change back to blue again
}[/as]
You can change any of the properties that are built into the Sprite class (alpha, etc), but you can also change any of the properties we wrote our own setter functions for! So in the above, we are able to change the background color on roll over, and do so VERY easily, I might add! We could have just as easily changed the font or the label text, or any of the other properties. Nice, eh?


Later, I will cover the use of embedded fonts. For now, if you were to set embedFonts to true for a button instance, your text would disappear. This is because the font must be embedded in the swf file somehow. One way to accomplish this is to have a font symbol in the library of the fla file that's set for "export for actionscript," and I'll demonstrate how to do that.

The MenuButton class is now finished! On the next page, we will take on the creation of the DropMenu class.

Creating the DropMenu Class
The DropMenu class is going to be composed of three basic parts: a heading, a panel, and a mask.

(Note: In the following discussion, I will sometimes refer to these parts using names without underscores in front of them. But the private properties in the class will always have an underscore. If the underscore is omitted in the following text, it's just because it makes for better prose).

So, in Flash, choose File / New... and choose Actionscript (AS) file. We'll begin with just the outline of a basic class, as before, and we will go ahead and create private variables for the three parts: _heading, _panel, and _mask. The heading is the button that serves as a masthead for the whole thing. The panel is going to be the stack of buttons that moves up and down behind the heading. The mask is going to be the window through which we see the panel moving up and down. The heading and the panel will be Sprite objects, and the mask can just be a Shape object:
[as]package {
    import flash.display.*;
    import flash.events.*;

    public class DropMenu extends Sprite {
        private var _heading:Sprite;
        private var _panel:Sprite;
        private var _mask:Shape;

        public function DropMenu(heading:Sprite = null) {
            _heading = heading;
            if (_heading != null) {
                draw();
            }
        }
        private function draw():void {
            addChild(_heading);
        }
    }
}[/as]
Also (in the above), I know I'm going to employ a draw() method again, so I go ahead and create one, and call it from the constructor. Once again, I want to get something on the screen that I can see, so I can begin the process of testing the movie and checking the progress. So, I put enough things in place so that I can send the constructor an instance of the MenuButton class and it will display it. The constructor's sole parameter, "heading," is made optional by giving it a default value of "null." In the constructor, I set the value of the _heading private variable to the value that was passed in. Then I test it to see if it got a null value (using an if statement), which would mean that no argument was supplied to the constructor. But if there was an argument supplied, it calls the draw() method, which in turn adds the _heading to the display list.

Save the above to the same folder and name it DropMenu.as. Next, let's go back to the fla file and put in some code to test it. Highlight everything on frame 1 and delete it. Replace it with the following lines:
[as]var btn:MenuButton = new MenuButton("My Dropdown Menu!");
var menu:DropMenu = new DropMenu(btn);
addChild(menu);[/as]
This code makes an instance of the MenuButton class with a custom label ("My Dropdown Menu!"). Then the next line creates a new instance of the DropMenu class, and passes to its constructor the instance of MenuButton that was just made on the previous line. Inside the class, the constructor runs, and since _heading is not null, the draw() method runs, and the passed-in heading Sprite is added to the display list of the menu. Finally, the menu is added to the (external) display list with addChild(menu). If not for this last line, nothing would display. As it is, so far what I see on the screen is visually no different than just adding the button to the display, but I do know that now I'm seeing my menu, so it's a start. The menu instance adds the btn object to its display list, and the fla file adds the menu object to its display list, and since the main timeline has already been added to the stage (which happens automatically), we get visual feedback. I have covered this before in my other articles that the main timeline of a fla file is already added to the stage for us automatically, behind the scenes. In the display hierarchy, any display object that's got an ultimate connection to the stage will be displayed (assuming that its x and y position doesn't place it out of view, of course).

To use the DropMenu class from the outside, the user of the class will make a new instance of it. They will either pass the heading to the constructor, or they will use the setter method we are going to make to set the heading. Next, in my conception of it anyway, they can start adding items to the menu using some kind of addItem() method, which will accept a Sprite as a parameter, and add it to the panel. That's why I knew I would need to employ a draw() method again, because I will have to tell the whole menu to redraw itself whenever the addItem() method runs and adds a new button to the panel. Not only will the item need to be added to the panel with addChild, but the mask will also have to be redrawn to a larger size whenever that happens. There is also the issue of y positioning, too, so I will need a variable that keeps track of the next available y position. I'll call it _currentY, so let's go ahead and add that to the variables list:
[as]private var _currentY:Number;[/as]

Now we need to work on the constructor some more. Having declared the _panel and _mask private variables, I need to instantiate them, and also initialize the _currentY variable with a value of 0. So add these lines to the constructor, but insert them at the beginning of it:
[as]_currentY = 0;
_panel = new Sprite();
_mask = new Shape();[/as]
Next, let's turn our attention the draw() method. First, let's borrow the while loop from the MenuButton class, which can be used verbatim. This will have the same effect it does in that other class; it will clear the display list. Again, insert these lines at the beginning of the function (ahead of the addChild(_heading) line):
[as]while(this.numChildren > 0) {
      this.removeChildAt(0);
}[/as]
Next, besides adding the heading to the display list, the draw() method also needs to position the panel and add it to the display list. Then it needs to draw the mask, and add the mask to the display list. But let's refer back to the drawing again:

Writing the draw() method
This drawing, like I stated before, will help us visualize how to position things. For example, where do we position the panel for its closed state? The x location we'll make equal to the heading's x, of course. The panel's y, though, can also be in relation the heading's y, but it's going to be the heading's y plus the heading's height, minus the panel's height. Translating that to code, add these lines to the draw() method (now place these lines just after the other lines that are there:
[as]_panel.x = _heading.x;
_panel.y = _heading.y + _heading.height - _panel.height;
addChild(_panel);[/as]
The next thing to draw is the mask. We make it the same width and height as the panel. But for positioning, it needs to be positioned just beneath the heading. Again, the drawing comes in handy, it let's you see a visualization of where to place the mask (the heading's y + the heading's height). By the way, whenever I make a mask, I find myself just using red for a fill color. You have to supply some kind of color, and I figure red is as good as any, and once it is made into a mask, it is never seen anyway. So, translating the above to code, add these lines to the draw() method (again, after everything else that is there already):
[as]_mask.graphics.clear();
_mask.graphics.beginFill(0xFF0000);
_mask.graphics.drawRect(0, 0, _panel.width, _panel.height);
_mask.graphics.endFill();
_mask.x = _heading.x;
_mask.y = _heading.y + _heading.height;
addChild(_mask);
_panel.mask = _mask;[/as]

Another brief aside, this time about using the drawing API
When you want to draw something using the drawing API (which is accessed via the graphics property of a display object), you have to keep in mind that each display object has its own coordinate space. Therefore, in the above, when we draw the mask, we want to use 0 and 0 for the x and y values that we send to the drawRect() method. We are telling the mask object (which is an instance of Shape) to draw a rectangle within itself, in other words, using its own coordinate space. After that, we can position the drawn shape by setting the x and y of the mask (Shape instance) itself. What we don't want to do is to send our desired x and y for positioning straight to the drawRect method. So draw first (usually starting at 0, 0), then position. The drawing happens within the shape, and the positioning happens from outside the shape, in other words.

Finally, since the draw() method could possibly be called from the constructor, and a heading may have been passed in as an argument, the draw method is going to have to add event listeners for ROLL_OVER and ROLL_OUT to the heading, so add these lines (again, after the lines that are there already):
[as]_heading.addEventListener(MouseEvent.ROLL_OVER, over);
this.addEventListener(MouseEvent.ROLL_OUT, out);[/as]
Notice that the event listener for rollover is added to the heading. But the event listener for rollout is added to this. What is this? The keyword this is a way of referring to the current object. When objects are made from this class, the word this will be the way of referring to each instance itself. Let me translate it to English for you. That line of code is saying, "when the mouse pointer rolls off of me (meaning this instance, or in other words, the whole menu), run the out method." This will have the following effect: When the mouse rolls over the heading, the panel will open. When the mouse rolls off of the whole thing (heading, panel, the whole works! --signified by this!), the panel will close.

One more final touch, and then we're done with the draw() method. It would seem wise to enclose the whole thing in an if statement, and make it conditional on whether or not the _heading variable is null. We know that we probably aren't going to misuse our new menu. We will probably always remember to make a heading for it before we start adding items to the panel. In fact, as it is, the draw method won't work unless the _heading variable is set first, so just to prevent the creation of a "headless" menu by ourselves or someone else, we will write it like this:
[as]if(_heading != null) {
    //
    //all of the draw() code we have written so far is enclosed here
    //
} else {
    throw new Error("Cannot draw DropDown menu. Please set heading first");
}[/as]
I know we already tested to see if the _heading was null in the constructor. But we need to do it here, too, because we are going to be calling this draw() method from other places besides the constructor. If the _heading is null, the else clause above will send a message to the output window that a heading needs to be set. This is just a reminder to another programmer (our ourselves at a later time) who might use our class. By the way, the Error class is a top level class, meaning that it doesn't need to be imported in order to use it.

Writing the "over" and "out" mouse handlers, and using TweenLite
Now we need to write the over and out functions that we just added event listeners for. Let's start with the over function, wherein the panel needs to open. But first, I am going to suggest that if you haven't already tried TweenLite (and related classes), that you head on over to this web page: http://www.greensock.com/tweenlite/ and click the "Download AS3" button you will see there. The greensock classes, which include TweenLite, are an excellent third party tweening library written by Mr. Jack Doyle. We will use the TweenLite class to make the menu open and close. When you download the classes, they will all be contained within a single com folder. All you need to do is make sure that this com folder is copied to our working folder (don't modify or move around the folders inside). If in doubt, just get the ZIP file at the end of this article, which will include it. Then, in our class, we just need to add the following import statement to use the TweenLite class (add this line to the list of import statements):
[as]import com.greensock.*;[/as]
Having done all that, let's create the over function (add this to the list of class functions, right after the draw function):
        [as]private function over(event:MouseEvent):void {
            TweenLite.to(_panel, 0.5, {y:_mask.y});
        }[/as]
The TweenLite class has a public static method called to(). Remember, public static methods belong to the class itself. This means that we don't need to make an instance of TweenLite in order to use the to() method. We just need to put the name of the class, a dot, and then to(), in order to use the method. The to() method of the TweenLite class requires three arguments to its parameter list. The first argument is the variable name of the object we want to tween (_panel). The second argument is the time we would like the tween to take, in seconds. In the above, I have specified half a second (0.5). The third argument needs to be supplied an object, which is why it's wrapped in curly braces. The curly braces are part of the actionscript language itself, and are just a shorthand way of specifying an object, the same way brackets are a shorthand way of enclosing an array. In any case, it's inside this object that we can specify whatever property of the object we want to tween. In our case, we want to tween the y property. So we put y, then a colon, then the value of the y location we want to tween to. Now here's where the magic happens. We can tween to a number, like 250, or whatever. But we can also supply an expression, a value from somewhere else in our program. Consulting the drawing above, where we want to tween to is, once again, _heading.y + _heading.height. But since the _mask object has already been placed at that location, it is easier to just say _mask.y.

Next, let's write the out function:
        [as]private function out(event:MouseEvent):void {
            TweenLite.to(_panel, 0.5, {y:_mask.y - _panel.height});
        }[/as]
You can see that the place to tween to is again in relation to the mask location. It should be pretty clear by now what is going on here. We tween the panel back to where it started from when the mouse rolls off of our menu object.

Here is the class so far (yours should now look like this):
[as]package {
    import flash.display.*;
    import flash.events.*;
    import com.greensock.*;

    public class DropMenu extends Sprite {
        private var _heading:Sprite;
        private var _panel:Sprite;
        private var _mask:Shape;
        private var _currentY:Number;

        public function DropMenu(heading:Sprite = null) {
            _currentY = 0;
            _panel = new Sprite();
            _mask = new Shape();
            _heading = heading;
            if (_heading != null) {
                draw();
            }
        }
        private function draw():void {
            if (_heading != null) {
                while (this.numChildren > 0) {
                    this.removeChildAt(0);
                }
                addChild(_heading);
                _panel.x = _heading.x;
                _panel.y = _heading.y + _heading.height - _panel.height;
                addChild(_panel);
                _mask.graphics.clear();
                _mask.graphics.beginFill(0xFF0000);
                _mask.graphics.drawRect(0, 0, _panel.width, _panel.height);
                _mask.graphics.endFill();
                _mask.x = _heading.x;
                _mask.y = _heading.y + _heading.height;
                addChild(_mask);
                _panel.mask = _mask;
                _heading.addEventListener(MouseEvent.ROLL_OVER, over);
                this.addEventListener(MouseEvent.ROLL_OUT, out);
            } else {
                throw new Error("Cannot draw DropDown menu. Please set heading first");
            }
        }
        private function over(event:MouseEvent):void {
            TweenLite.to(_panel, 0.5, {y:_mask.y});
        }
        private function out(event:MouseEvent):void {
            TweenLite.to(_panel, 0.5, {y:_mask.y - _panel.height});
        }
    }
}[/as]
There are only two more functions to write in this class: the setter method for the heading, and the addItem() method, and then we will be able to test the DropMenu class and see it working. See you on the next page, where we will do all that and more!


Further refining the DropMenu class
The two remaining functions are now surprisingly easy to write. First, we need to make a function that sets a heading for the menu. This is the setter function that can be used from outside the class, in the case where a heading wasn't sent to the class's constructor:
        [as]public function set heading(value:Sprite):void {
            _heading = value;
            draw();
        }[/as]
Next, we just need to write the addItem() function. This function will accept a Sprite object as a parameter:
        [as]public function addItem(item:Sprite):void {
            item.y = _currentY;
            _panel.addChild(item);
            _currentY += item.height;
            draw();
        }[/as]
Notice, after setting the passed in Sprite's y position to the _currentY, the Sprite (known as item in the function body) is simply added to the display list of the panel. The _currentY variable then has its value adjusted by incrementing it (adding to its existing value) with item's height. This gets it ready for the next item to be added, should the function be called again. Finally, draw() is called. Remember, draw() will remove everything from the display list and add it all back again, including redrawing the mask to match the size of the panel!

Here is the completed DropMenu class:
[as]package {
    import flash.display.*;
    import flash.events.*;
    import com.greensock.*;
   
    public class DropMenu extends Sprite {
        private var _heading:Sprite;
        private var _panel:Sprite;
        private var _mask:Shape;
       
        private var _currentY:Number;
   
        public function DropMenu(heading:Sprite = null) {
            _currentY = 0;
            _panel = new Sprite();
            _mask = new Shape();
            _heading = heading;
            if(_heading != null) {
                draw();
            }
        }
        public function draw():void {
            if(_heading != null) {
                //first remove any existing elements, if any:
                while(this.numChildren > 0) {
                    this.removeChildAt(0);
                }
                addChild(_heading);
                _panel.x = _heading.x;
                _panel.y = _heading.y + _heading.height - _panel.height;
                addChild(_panel);
               
                _mask.graphics.clear();
                _mask.graphics.beginFill(0xFF0000);
                _mask.graphics.drawRect(0, 0, _panel.width, _panel.height);
                _mask.graphics.endFill();
                _mask.x = _heading.x;
                _mask.y = _heading.y + _heading.height;
                addChild(_mask);
                _panel.mask = _mask;
                //add event listeners:
                _heading.addEventListener(MouseEvent.ROLL_OVER, over);
                this.addEventListener(MouseEvent.ROLL_OUT, out);
            } else {
                throw new Error("Cannot draw DropDown menu. Please set heading first");
            }
        }
        private function over(event:MouseEvent):void {
            TweenLite.to(_panel, 0.5, {y:_mask.y});
        }
        private function out(event:MouseEvent):void {
            TweenLite.to(_panel, 0.5, {y:_mask.y - _panel.height});
        }
        public function set heading(value:Sprite):void {
            _heading = value;
            draw();
        }
        public function addItem(item:Sprite):void {
            item.y = _currentY;
            _panel.addChild(item);
            _currentY += item.height;
            draw();
        }
    }
}[/as]
Taking the DropMenu class out for a test drive
Cool! Now we can turn our attention again to the fla file and test all this out. Delete the code from frame 1 of the fla file, and paste in this instead:
[as]var btn:MenuButton = new MenuButton();
btn.label = "My new menu is cool!";
btn.fontColor = 0xFFFFFF; //white
btn.width = 250;
btn.height = 40;
btn.fontSize = 18;
btn.backgroundColor = 0xFF0000; // red

var menu:DropMenu = new DropMenu();
menu.x = menu.y = 50;
addChild(menu);
menu.heading = btn;

var btn2:MenuButton = new MenuButton();
btn2.label = "This is the first item!";
btn2.fontColor = 0xFFFFFF; //white
btn2.width = 250;
btn2.height = 40;
btn2.fontSize = 18;
btn2.backgroundColor = 0x00FF00; //green

menu.addItem(btn2);

var btn3:MenuButton = new MenuButton();
btn3.label = "This is the second item!";
btn3.fontName = "Times New Roman";
btn3.fontColor = 0xFFFFFF; //white
btn3.width = 250;
btn3.height = 40;
btn3.fontSize = 20;
btn3.backgroundColor = 0x0000FF; //blue

menu.addItem(btn3);

var btn4:MenuButton = new MenuButton();
btn4.label = "This is the third item!";
btn4.fontColor = 0xFFFFFF; //white
btn4.width = 250;
btn4.height = 40;
btn4.fontSize = 18;
btn4.backgroundColor = 0x999999; //gray

menu.addItem(btn4);[/as]
This is a long block of code, I know, but if you read it over, it ought to be pretty obvious to you everything it's doing. We are simply using all those setter functions we made in the MenuButton class, and now you can see how easily we can play around with different settings and change fonts, colors, or whatever we want! We can also do silly stuff like make some of the buttons shorter or less wide than others. Whatever we do, the DropMenu class seems to handle it just fine! By the way, we also have the option of sending all of the settings to the constructor instead, like so:
[as]var btn:MenuButton = new MenuButton("My new menu is cool", "Arial", 18, 0xFFFFFF, false, 0xFF0000, 250, 40);

var menu:DropMenu = new DropMenu(btn);
menu.x = menu.y = 50;
addChild(menu);

var btn2:MenuButton = new MenuButton("This is the first item!", "Arial", 18, 0xFFFFFF, false, 0x00FF00, 250, 40);
var btn3:MenuButton = new MenuButton("This is the second item!", "Times New Roman", 20, 0xFFFFFF, false, 0x0000FF, 250, 40);
var btn4:MenuButton = new MenuButton("This is the third item!", "Arial", 18, 0xFFFFFF, false, 0x999999, 250, 40);

menu.addItem(btn2);
menu.addItem(btn3);
menu.addItem(btn4);[/as]
The above code block does exactly the same thing as the former. I myself prefer setting properties individually, because then I don't have to memorize their order. But it's nice that we have the option. You can also add click handlers to the buttons as well, even after they have been added to the menu. Unlike the old Actionscript 2.0 days, there isn't all of that nesting going on anymore. The buttons have been added to the display list of the menu, but they aren't nested, and can still be programmed without all those complicated paths and dot syntax we used to have to do. For example, add these lines to the end of the code:
[as]btn4.addEventListener(MouseEvent.CLICK, btn4Click);
function btn4Click(event:MouseEvent):void {
    btn4.label = "You clicked me!!";
    btn4.backgroundColor = 0x000000; //black
}[/as]
(Because of the way I numbered the buttons, btn4 is actually the third item on the dropdown, but you get the idea). I am also having a bit of fun with the properties in the above. You can see that when the third item is clicked, rather than just tracing a message (like I am always so inclined to do), I just change the label of the button, and turn it's background color to black, just for good measure! Here's a working demo:

(Click the third dropdown item and watch it change its message and background color!)

Well, now the DropMenu class is finished. But, like all the TV infomercial pitchmen are inclined to say, "But wait, there's MORE!" For one thing, I need to cover embedded fonts like I mentioned earlier, and how they affect the menu buttons. Then I am going to demonstrate how the DropMenu class isn't limited to just using instances of the MenuButton class! All that and more on the next page!



Embedded fonts, and other special effects
I mentioned earlier that I would explain how to embed fonts in the swf file. This is icing on the cake for this article, and I want to make it clear that I am only going to cover one method of font embedding. There are at least a couple more, but I don't to make this an article on font embedding (I may be saving that one for later, I suppose!).

In the flash authoring tool, you will notice in the library panel an obscure little triangle:


When you click this triangle shaped button, you will get the following menu (Note, you can also get this same menu just by right-clicking the library itself on an empty space):


Choose New Font... from the menu. When you do, you will get a font symbol added to the library. Now we just need to make sure that this font symbol has the font we want, and that it's set for export for actionscript. Right-click the symbol and choose Properties, and you will get this dialog box. Let's embed the Arial font, and export it for actionscript:


Click OK. Flash will next give you the familiar dialog box that says the class cannot be found, and so it will make one for you, etc, etc! Click OK again. That's all there is to it! Now the font will be embedded in the swf file. Bear in mind that this increases your file size a bit (no, I don't have any figures for you, so you can conduct your own experiment to determine how much). Now let's consider what embedding a font does for us. If the end user doesn't have the font on their system, we can be sure that they will still see the font anyway. Also, embedded fonts can do some things and be transformed in ways that non-embedded fonts can't. For example, one of these things is rotation. Now that the font is embedded, let's return to the fla file. Delete all the code on frame 1 again, and paste in the following. This time we will set the embedFonts property to true for each of the buttons:
[as]menu.x = menu.y = 50;
addChild(menu);
menu.heading = btn;

var btn2:MenuButton = new MenuButton();
btn2.label = "This is the first item!";
btn2.fontColor = 0xFFFFFF; //white
btn2.width = 250;
btn2.height = 40;
btn2.fontSize = 18;
btn2.backgroundColor = 0x00FF00; //green
btn2.embedFonts = true;

menu.addItem(btn2);

var btn3:MenuButton = new MenuButton();
btn3.label = "This is the second item!";
//btn3.fontName = "Times New Roman";
btn3.fontColor = 0xFFFFFF; //white
btn3.width = 250;
btn3.height = 40;
btn3.fontSize = 20;
btn3.backgroundColor = 0x0000FF; //blue
btn3.embedFonts = true;

menu.addItem(btn3);

var btn4:MenuButton = new MenuButton();
btn4.label = "This is the third item!";
btn4.fontColor = 0xFFFFFF; //white
btn4.width = 250;
btn4.height = 40;
btn4.fontSize = 18;
btn4.backgroundColor = 0x999999; //gray
btn4.embedFonts = true;

menu.addItem(btn4);

btn4.addEventListener(MouseEvent.CLICK, btn4Click);
function btn4Click(event:MouseEvent):void {
    btn4.label = "You clicked me!!";
    btn4.backgroundColor = 0x000000; //black
}[/as]
Notice the line at the end of each code block that sets the embedFonts property to true for that button. I commented out the line that set the fontName to "Times New Roman" for the second button, since we didn't embed that font. If you set embedFonts to true, but then you don't embed the font, the text won't show up (try running this both ways, with this line commented and then with it uncommented, and you will see the text disappear for the second button in the panel).

When you run the file, it won't look any different than it did before, but if someone didn't have Arial on their system, they would still see your font. However, let's now proceed to give our menu a little bit of a "tilt" (add this line to the end of the above code):
[as]menu.rotation += 10;[/as]
Here's the resulting swf from the above code:

Okay, yeah, I know, maybe it's a bit silly, but it does demonstrate that with an embedded font you can do transformations like this that you can't do with device fonts. If you tried rotating this menu without setting embedFonts to true (or without having the fonts actually embedded, of course), all the text will disappear.

Extra bonus tip on font embedding: We've all had a few hair-pulling experiences with Flash, I suppose: those late night sessions where something isn't working right, and it drives us to Google to search out what the problem is (and costs up to several hours!). One of mine was when I was embedding a font, and using it for some scrolling text. Some of the text had to be bold. The bold text just would not show up, no matter what I did. I Googled my dilemma, trying to think of the right search terms. Anyway, it turned out that if you want to use bold fonts, you have to embed the same font again with bold selected. That would mean two symbols in the library for Arial (in this case), both set for export and one having Regular selected and the other having Bold selected. I just thought I'd pass that along, since it took me so long to find it. Maybe someone will benefit.

Using the DropMenu class with other content
You might have noticed that you can use the DropMenu class by sending it instances of the MenuButton class. And yet, the DropMenu class doesn't depend on the MenuButton class. Notice that DropMenu's addItem() method, and the set heading() method, both expect to receive a Sprite object. Since the MenuButton class extends Sprite, instances of MenuButton certainly qualify. But so does anything that's a member of any class that extends Sprite, even MovieClip symbols or instances of classes that extend MovieClip.

So to round out this article, I am going to demonstrate a DropMenu menu that uses a MenuButton instance for the heading, but uses some other (hand crafted) MovieClip instances for the dropdown items. We can actually make anything at all be an item in the DropMenu, as long as it's got Sprite in its ancestry somewhere! Which is pretty versatile indeed, since Sprite is a container! I am including this demo file in the ZIP also, which you can download at the end of this page, below. I threw this together pretty quickly using some small image files and some text copied and pasted from Wikipedia. So please, just consider it a really quick demo of the possibilities, and not any kind of attempt at a finished piece. I didn't even put in click listeners or turn on buttonMode, but I could do all of that if I had a good reason to. Hopefully this will just help spark your own imagination.

In conclusion, I'd like to say that of all the articles I've done so far, this one seems to have sparked my own imagination the most. Some of the things that the menu could do surprised me, especially considering how easy the classes were to make. A lot of ideas come to mind, such as making more classes that also extend Sprite but that do other specialized things, instances of which can be sent to the menu instead of MenuButton instances. Plus the idea that you can mix them and match them however you like. It also ought to be obvious that you can easily make more instances of the menu, and so build a full menu bar if you want. Since the DropMenu is itself a Sprite, you could also have menus within menus. That is, use addItem() to add other DropMenu instances to a DropMenu! Another (related) enhancement might be a Submenu class where the menus open to the side of the header instead. Yet another enhancement might be some kind of scrollbar in the dropdown panel, to make menus that are too long for the display. You could also work in some kind of 3-D content somehow. Have I sparked any ideas yet?

As always, consider this as a springboard, the tip of the iceberg. I hope I've helped you realize that creating custom classes is one of the most creative and healthy addictions you can have! It's just plain fun!

See you next time, happy coding. Thanks for your comments, and send me a link to your stuff!

Mr. Jody Hall
Feb 18, 2010