Accessibility
 
Home / Developer Center / Macromedia Flash Developer Center /

Macromedia Flash Article

Icon or Spacer Icon or Spacer Icon or Spacer
Nigel Pegg
Nigel Pegg
Component Engineer

www.dragspace.com

Extending v1 components: Customizing the ListBox component


Note: The techniques in this article work with v1 of the Macromedia Component Architecture, native to Macromedia Flash MX. Macromedia Flash MX 2004 users can use the techniques in this article if they use v1 components and publish to Macromedia Flash Player 6. For more information on using cell renderers with ActionScript 2.0 and v2 components, see the following resources:


Introduction
This tutorial describes how to customize the ListBox or ComboBox UI Components so they display a customized item symbol (such as an icon) next to label choices. In this tutorial, you'll create the Macromedia Flash application below. Download the sample file, customItem.fla (231 KB), to follow along with this tutorial.


This sample file requires the latest version of the Macromedia Flash Player.

Download it now.


Prerequisites
To use this tutorial, you'll need to have the Macromedia Flash MX authoring tool installed.

Item symbol and data provider model
The ListBox and ComboBox follow a standard data/view display model. The data (the data provider) and view (the item symbol) are deliberately kept separate. This makes the components more flexible and easy to modify.

It is more common to extend the item symbol than the data provider. The data provider used is pretty flexible, and will suffice for the most common (linear-array based) cases. However, for the adventurous, the DataProvider class can be found in the Library, after dragging a component to the Stage, in Flash UI Components > Core Assets > FUI Component Class Tree.

The FListBoxItem and FComboBoxItem (located at Flash UI Components > Core Assets > FUI Component Class Tree > FUI Component SubClasses > FSelectable Item Subclasses) are both templates that help you extend the item symbol. Both of these classes extend FSelectableItem, which has extensive comments to ensure easier subclassing, and where you will start writing to create your own item symbol.

How to create a custom list item symbol

Data model
To create a custom list item, first decide on the data model that the item will need in order to display its content. Typically, you can use the "data" field for each item to store additional item information. For this sample, the code looks like the following:

list.addItem("Jim", "happy");
list.addItem("Bob", "sad");
list.addItem("Sally", "sad");
list.addItem("Doug", "happy");
list.addItem("Leslie", "happy");
list.addItem("George", "happy");
list.addItem("Debbie", "sad");
list.addItem("Sully", "happy");
list.addItem("Belle", "sad");
list.addItem("Justin", "happy");

For this sample, the included data is a simple flat structure, but is sufficient for the example. Imagine that with a more complex ListBox, you might use a more complex structure, as follows:

list.addItem("Jim", { feeling:"happy", hair:0xff0000, eyes:0x0000ff });

Note that in this case, the data field is an object that contains information for feeling (happy/sad), hair color, and eye color. The item symbol interprets the data field value and displays the appropriate graphic.

Creating a custom list item movie clip and class
Use the steps below to create a custom item symbol:


1
Duplicate the FListBoxItem symbol in your library.
2
Name it FCustomItem.This template holds all the basic references you'll need to extend from FSelectableItem.
3

Replace FCustomItemClass with FListBoxItemClass in the FCustomItem, as follows:

FListBoxItem FCustomItem

#initclip 3
/*
FListItemClass
EXTENDS FSelectableItemClass
This is mostly a code stubb for extension purposes.
*/

function FListItemClass()
{
   this.init();
}

FListItemClass.prototype = new FSelectableItemClass();
Object.registerClass("FListItemSymbol", FListItemClass);

#endinitclip

#initclip 3
/*
FCustomItemClass
EXTENDS FSelectableItemClass
This is a customized List Item
*/

function FCustomItemClass()
{
    this.init();
}

FCustomItemClass.prototype = new FSelectableItemClass();
Object.registerClass("FCustomItemSymbol", FCustomItemClass);

 

#endinitclip


In short, you only replace FListItemClass with FCustomItemClass to create the new custom item symbol. Note that the #initclip number (order) does not need to be changed, and that the new class still inherits the methods and properties of the FSelectableItemClass. This is discussed next.

Look out for linkage IDs
Ensure that the linkage ID for your FCustomItem symbol is correct. In the following call:

Object.registerClass("FCustomItemSymbol", FCustomItemClass);

The class object is linked to "FCustomItemSymbol." To link your item symbol, right-click Library. Select the "Linkage..." dialog, and ensure the following:


1
That the Identifier field is set to "FCustomItemSymbol."
2
That "Export in First Frame" is set to ON (checked).

Extending FSelectableItemClass
At this point, it's worth taking a peek inside the FSelectableItem symbol, which has the base code for all list and combo items. There are three methods that mention in the comments that they are potentially worth extending:

1
FSelectableItemClass.prototype.layoutContent(width)
2
FSelectableItemClass.prototype.displayContent(itmObj, selected)
3

FSelectableItemClass.prototype.setEnabled(enable)

Note that this last method is optional and will not be discussed in this tutorial.


Extension #1: FCustomItemClass.prototype.layoutContent
The layoutContent(width) method controls which content pieces are passed into the item as it's created. The original code:

FSelectableItemClass.prototype.layoutContent = function(width)
{
   this.attachMovie("FLabelSymbol", "fLabel_mc", 2, {hostComponent:this.controller});
   this.fLabel_mc._x = 2;
   this.fLabel_mc._y = 0;
   this.fLabel_mc.setSize(width-2);
   this.fLabel_mc.labelField.selectable = false;
}

Only adds a label to the item and sets its position and width based on the width value passed.

For this tutorial, you will add the label to the item, and then add a happy/sad icon to the label. Use the following steps:


1
Create a symbol with two frames (happy and sad). Name it Happy-Sad Icon.
2
Add it to the stage on a new layer inside the item symbol. The instance name should be: icon_mc.
3

Override the layoutContent method in FCustomItemClass so that you can layout the icon_mc next to the label.

FCustomItemClass.prototype.layoutContent = function(width)

{

   this.attachMovie("FLabelSymbol", "fLabel_mc", 2, {hostComponent:this.controller});
   this.fLabel_mc._x = 2;
   this.icon_mc._x = width - this.icon_mc._width - 5;
   this.fLabel_mc.setSize(width-7-this.icon_mc._width);
   this.fLabel_mc.labelField.selectable = false;
}


These small changes enable the icon to share space with the label. You could extend this further to incorporate layouts with numerous labels, icons, or components inside the item symbol. These can either be added dynamically with attachMovie in this method (for instance, the fLabel_mc in this case), or in authoring time, on a layer in the Item Symbol itself (for example, the icon_mc). In general, in order for the items to compensate for variable sizes, this method must be responsible for managing the size and position of all the assets inside the item, whether dynamically placed or done at the authoring step.

Extension #2: FCustomItemClass.prototype.displayContent
Lastly, you'll extend the displayContent method. The original code uses a lot of logic to determine the text that is passed to the label field. To keep this code intact, add the following code in FCustomItemClass :

FCustomItemClass.prototype.displayContent = function(itmObj, selected)
{
   super.displayContent(itmObj, selected);
   var myColor = new Color(this.icon_mc);
   if (selected) {
      var myColorTransform = { ra: -100, rb: 255, ga: 172, gb: 0, ba: 100, bb: 83, aa: 100, ab: 255};
   } else {
      var myColorTransform = { ra: 100, rb: 0, ga: 100, gb: 0, ba: 100, bb: 0, aa: 100, ab: 0};
   }
   myColor.setTransform(myColorTransform);

   this.icon_mc.gotoAndStop((itmObj.data=="happy") ? 1 : 2);
}

The displayContent method takes two simple parameters: itmObj (an object comprised of the .label and .data fields added during addItem) and selected (a boolean value that indicates whether the item is selected or not). The following explains what happens in the code snippet above.


1
The params are sent to the superClass' implementation of the method. This will ensure that the label is filled with the appropriate text.
2
Next, it applies a color transform to icon_mc, depending on whether the item is selected or not. This makes the green-tinted happy face appear when selected, and a yellow-tinted happy face appear when it is not selected.
3

The itmObj.data determines if this item represents a happy or sad person. Remember, at the beginning of this example, we used the following :

list.addItem("Jim", "happy");

This means that .data for each object was being filled with a "happy" or "sad" value. Depending on the contents of .data, the icon_mc flips from either the happy frame (1) or the sad frame (2). You can extend this idea to use the .data field with any kind of object or primitive data and render the item with any number of details (such as icons, text fields, components, and so forth) depending on the contents of the field.


Warning
Under the following conditions, the ListBox can stop working:

If you base the height of the item on an FLabel field.

If you are not using .label as the property to fill the FLabel.
Luckily, it is easy to workaround this situation. In the displayContent method, simply add the following lines to the beginning of the method:

if (itmObj.label == "Sizer: PjtTopg") {

yourFLabel.setLabel(itmObj.label);
return;

}

Replace "yourFLabel" with the instance name of the FLabel upon which the size of the item is based.


Note that these are the only two methods needed to add, layout, and display extra content in a list item.

The last step: setItemSymbol
Lastly, you'll learn how to get the ListBox to use your item symbol choice. The call is a method of the component named: setItemSymbol. In our sample file, the call is made on the timeline containing the ListBox, and looks like the following:

listBox.setItemSymbol("FCustomItemSymbol");

The ListBox uses your custom item symbol for displaying the items. This functionality allows you to create a library of different item symbols and dynamically swap them as different views for the same data model.


About the author
Raised in the wilds of northern Canada, Nigel's keen instincts for Macromedia Flash were honed fighting his way through caribou herds, computing science departments, and multimedia design firms of the pre-burst Internet economy. A "veteran" to web design/development since 1996 (Perl!) and Macromedia Flash 3, Nigel came to Macromedia to focus on applying his "serious" degree to his passion for Macromedia Flash, and somehow ended up making a whole pile of what they're calling "Macromedia Flash UI Components."