Component Class – Part Two

In the previous article I showed you how to make a component based on an existing MXML component, the HBox. In this article we’ll look at writing that same component in ActionScript. I think this is a worthwhile exercise because you’ll see how similar MXML and ActionScript components are.

One good thing to try is to add
-keep-generated-actionscript=true to your Flex compiler options. MXML files are first translated into ActionScript classes, then compiled into the SWF file. The
-keep-generated-actionscript switch will leave those translations and you can compare what we’re about to do with what the compiler has generated.

Take a look at the V1 MXML component. There are four parts to it: the root tag (the HBox), the Event metadata, the Script block, and the child components (LinkButton and Image). You’ll see how these elements are reflected when you write the ActionScript version of the component.

Download the Source

This is the source code for this example in a package structure. The file for the icon is included.

Create a new ActionScript class called CycleSelectButtonV2 and have it extend HBox. Use the Flex Builder wizard if you can. Otherwise create the class using the following code:

package com.adobe.examples.buttons
{
import mx.containers.HBox;

public class CycleSelectButtonV2 extends HBox
{
public function CycleSelectButtonV2()
{
super();
}
}
}  

One of the four elements has already been taken care of: the class extends HBox.

The MXML component also includes event metadata. Add that to the ActionScript class just above the class definition:

package com.adobe.examples.buttons
{
import mx.containers.HBox;

 [Event(name="change",type="flash.events.Event")]

public class CycleSelectButtonV2 extends HBox
{
...  

The child components, Image and LinkButton, require ActionScript code. In the first article of this series you read how the Flex framework operates with properties being set, with commitProperties() being called, and so forth. Creating child components is also part of that framework.

When a component is being created the Flex framework invokes its
createChildren() function. This is as true for Buttons as it is for Container classes like HBox. To create the LinkButton and Image components, you’ll need to add your own override of createChildren().

Below the import statement for HBox in the V2 ActionScript file, add:

import mx.controls.LinkButton;
import mx.controls.Image;  

The MXML tags for Image and LinkButton created two members of the class. You’ll do the same here, below the class constructor function:

private var linkButton:LinkButton;
private var image:Image;  

Component children in MXML files are public. I like to make them private, but you can use protected or public if you like.

You also need to bring in the cycle button graphic. In the MXML file it was embedded directly in the Image tag. There is no ActionScript equivalent for that. Instead, add this code below the variable declarations:

[Embed(source="../assets/cycle_component.gif")]
private var cycleIcon:Class;  

The embed metadata tells the compiler to grab the bytes from the file and generate a class to make an image out of them. The data type of the cycleIcon variable is
Class because you don’t want to have duplicates of the image (takes too much memory) but rather have shared instances that refer to those bytes.

Now add the createChildren() function:

override protected function createChildren() : void
{
image = new Image();
image.width = 20;
image.height = 20;
image.source = cycleIcon;
addChild(image);
linkButton = new LinkButton(); addChild(linkButton); super.createChildren(); }

An instance of the Image class is created, then its width and height are set as is its source property. The LinkButton is also created. Notice how both components are added as children to the component using
addChild() . This puts the children onto the component’s display list. If you do not do this the children will not appear. Creating the component children with
new and using
addChild() is equivalent to the MXML tags.

The createChildren function is called before commitProperties() so that you can apply properties to the children. You should now copy the commitProperties() function, along with the setter and getter property functions from the V1 class.

With the LinkButton and Image child components created and set, you’ve knocked off another MXML component equivalent.

In the previous article, you read that part of the Flex framework includes the measurement of the components. One of the big things the MXML component does for you is figure out the size of everything and where to place it. You’ll have to do that yourself with an ActionScript component.

Because we are using HBox as the base class for the component, the sizing and positioning of the children are taken care of. Later, when we write this component from scratch, you’ll see how to do that for yourself.

At this point the only thing missing is the click event handler on the LinkButton. To add that, go back into the createChildren() method and add the following line after the linkButton has been created:

linkButton.addEventListener(MouseEvent.CLICK, handleClick);  

You’ll need to include an import statement for
flash.events.MouseEvent with the other import statements.

Using addEventListener() is the equivalent of putting the event handler in the MXML tag.

Now copy the handleClick() function from the V1 component and make the change shown:

private function handleClick( event:MouseEvent ) : void
{
selectedIndex = selectedIndex + 1;

// wrap back to zero if more than the # of items in the dataProvider.
if( selectedIndex >= dataProvider.length ) selectedIndex = 0;

dispatchEvent( new Event(Event.CHANGE) );
}  

When you are using MXML tags you have the luxury of deciding what, if any, arguments to pass to an event handler. When using addEventListener the event handler function must take a single argument of some event type. If you read the documentation on the LinkButton and look at the click event, you’ll see it dispatches a MouseEvent, so that’s the type of data that will be passed.

Open the main Flex application and change the tag from CycleSelectButtonV1 to CycleSelectButtonV2 and run it. The component should look and behave the same way.

Rotating the Arrows

I said in the previous article that, in addition to writing this component in ActionScript, we’d also rotate the arrow cycle each time the LinkButton was clicked. I’ve included the code to do that in the source download, replacing the Image. Take a look and it will be the topic of the next article in this series.