About creating advanced MX components

Simple visual components are subclasses of existing Flex components that modify the appearance of the component by using skins or styles, or add new functionality to the component. For example, you add a new event type to a Button control, or modify the default styles or skins of a DataGrid control. For more information, see Create simple visual components in ActionScript.

In advanced components, you typically perform the following actions:

  • Modify the visual appearance or visual characteristics of an existing component.

  • Create a composite component that encapsulates two or more components within it.

  • Create a component by creating a subclass of the UIComponent class.

You usually create a component as a subclass of an existing class. For example, to create a component that is based on the Button control, you create a subclass of the mx.controls.Button class. To make your own component, you create a subclass of the mx.core.UIComponent class.

About overriding protected UIComponent methods for MX components

All Flex visual components are subclasses of the UIComponent class. Therefore, visual components inherit the methods, properties, events, styles, and effects defined by the UIComponent class.

To create an advanced visual component, you must implement a class constructor. Also, you optionally override one or more of the following protected methods of the UIComponent class:

UIComponent method

Description

commitProperties()

Commits any changes to component properties, either to make the changes occur at the same time or to ensure that properties are set in a specific order.

For more information, see Implementing the commitProperties() method for MX components.

createChildren()

Creates any child components of the component. For example, the ComboBox control contains a TextInput control and a Button control as child components.

For more information, see Implementing the createChildren() method for MX components.

layoutChrome()

Defines the border area around the container for subclasses of the Container class.

For more information, see Implementing the layoutChrome() method for MX components.

measure()

Sets the default size and default minimum size of the component.

For more information, see Implementing the measure() method for MX components.

updateDisplayList()

Sizes and positions the children of the component on the screen based on all previous property and style settings, and draws any skins or graphic elements used by the component. The parent container for the component determines the size of the component itself.

For more information, see Implementing the updateDisplayList() method for MX components.

Component users do not call these methods directly; Flex calls them as part of the initialization process of creating a component, or when other method calls occur. For more information, see About the component instantiation life cycle for MX components.

About the invalidation methods for MX components

During the lifetime of a component, your application might modify the component by changing its size or position, modifying a property that controls its display, or modifying a style or skin property of the component. For example, you might change the font size of the text displayed in a component. As part of changing the font size, the component’s size might also change, which requires Flex to update the layout of the application. The layout operation might require Flex to invoke the commitProperties(), measure(), layoutChrome(), and the updateDisplayList() methods of your component.

Your application can programmatically change the font size of a component much faster than Flex can update the layout of an application. Therefore, you should only want to update the layout after you are sure that you’ve determined the final value of the font size.

In another scenario, when you set multiple properties of a component, such as the label and icon properties of a Button control, you want the commitProperties(), measure(), and updateDisplayList() methods to execute only once, after all properties are set. You do not want these methods to execute when you set the label property, and then execute again when you set the icon property.

Also, several components might change their font size at the same time. Rather than updating the application layout after each component changes its font size, you want Flex to coordinate the layout operation to eliminate any redundant processing.

Flex uses an invalidation mechanism to synchronize modifications to components. Flex implements the invalidation mechanism as a set of methods that you call to signal that something about the component has changed and requires Flex to call the component’s commitProperties(), measure(), layoutChrome(), or updateDisplayList() methods.

The following table describes the invalidation methods:

Invalidation method

Description

invalidateProperties()

Marks a component so that its commitProperties() method gets called during the next screen update.

invalidateSize()

Marks a component so that its measure() method gets called during the next screen update.

invalidateDisplayList()

Marks a component so that its layoutChrome() and updateDisplayList() methods get called during the next screen update.

When a component calls an invalidation method, it signals to Flex that the component must be updated. When multiple components call invalidation methods, Flex coordinates updates so that they all occur together during the next screen update.

Typically, component users do not call the invalidation methods directly. Instead, they are called by the component’s setter methods, or by any other methods of a component class as necessary. For more information and examples, see Implementing the commitProperties() method for MX components.

About the component instantiation life cycle for MX components

The component instantiation life cycle describes the sequence of steps that occur when you create a component object from a component class. As part of that life cycle, Flex automatically calls component methods, dispatches events, and makes the component visible.

The following example creates a Button control in ActionScript and adds it to a container:

// Create a Box container. 
var boxContainer:Box = new Box(); 
// Configure the Box container.  
 
// Create a Button control.  
var b:Button = new Button() 
// Configure the button control. 
b.label = "Submit"; 
... 
// Add the Button control to the Box container. 
boxContainer.addChild(b);

The following steps show what occurs when you execute the code to create the Button control, and add the control to the Box container:

  1. You call the component’s constructor, as the following code shows:

    // Create a Button control.  
    var b:Button = new Button()
  2. You configure the component by setting its properties, as the following code shows:

    // Configure the button control. 
    b.label = "Submit";

    Component setter methods might call the invalidateProperties(), invalidateSize(), or invalidateDisplayList() methods.

  3. You call the addChild() method to add the component to its parent, as the following code shows:

    // Add the Button control to the Box container. 
    boxContainer.addChild(b);

    Flex then performs the following actions:

  4. Sets the parent property for the component to reference its parent container.

  5. Computes the style settings for the component.

  6. Dispatches the preinitialize event on the component.

  7. Calls the component’s createChildren() method.

  8. Calls the invalidateProperties(), invalidateSize(), and invalidateDisplayList() methods to trigger later calls to the commitProperties(), measure(), or updateDisplayList() methods during the next render event.

    The only exception to this rule is that Flex does not call the measure() method when the user sets the height and width of the component.

  9. Dispatches the initialize event on the component. At this time, all of the component’s children are initialized, but the component has not been sized or processed for layout. You can use this event to perform additional processing of the component before it is laid out.

  10. Dispatches the childAdd event on the parent container.

  11. Dispatches the initialize event on the parent container.

  12. During the next render event, Flex performs the following actions:

    1. Calls the component’s commitProperties() method.

    2. Calls the component’s measure() method.

    3. Calls the component’s layoutChrome() method.

    4. Calls the component’s updateDisplayList() method.

    5. If steps 13 and 14 are not required, which is the most common scenario, dispatches the updateComplete event on the component.

  13. Flex dispatches additional render events if the commitProperties(), measure(), or updateDisplayList() methods call the invalidateProperties(), invalidateSize(), or invalidateDisplayList() methods.

  14. After the last render event occurs, Flex performs the following actions:

    1. Makes the component visible by setting the visible property to true.

    2. Dispatches the creationComplete event on the component. The component is sized and processed for layout. This event is only dispatched once when the component is created.

    3. Dispatches the updateComplete event on the component. Flex dispatches additional updateComplete events whenever the layout, position, size, or other visual characteristic of the component changes and the component is updated for display.

Most of the work for configuring a component occurs when you add the component to a container by using the addChild() method. That is because until you add the component to a container, Flex cannot determine its size, set inheriting style properties, or draw it on the screen.

You can also define your application in MXML, as the following example shows:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"> 
    <mx:Box> 
        <mx:Button label="Submit"/> 
    </mx:Box> 
</s:Application>

The sequence of steps that Flex executes when creating a component in MXML are equivalent to the steps described for ActionScript.

You can remove a component from a container by using the removeChild() method. If there are no references to the component, it is eventually deleted from memory by the garbage collection mechanism of Adobe® Flash® Player or Adobe® AIR™.

About the steps for creating a component for MX components

When you implement a component, you override component methods, define new properties, dispatch new events, or perform any other customizations required by your application.

To implement your component, follow these general steps:

  1. If necessary, create any skins for the component.

  2. Create an ActionScript class file.

    1. Extend one of the base classes, such as UIComponent or another component class.

    2. Specify properties that the user can set by using an MXML tag property.

    3. Embed any graphic and skin files.

    4. Implement the constructor.

    5. Implement the UIComponent.createChildren() method.

    6. Implement the UIComponent.commitProperties() method.

    7. Implement the UIComponent.measure() method.

    8. Implement the UIComponent.layoutChrome() method.

    9. Implement the UIComponent.updateDisplayList() method.

    10. Add properties, methods, styles, events, and metadata.

  3. Deploy the component as an ActionScript file or as a SWC file.

For more information about MXML tag properties and embedding graphic and skin files, see Create simple visual components in ActionScript.

You do not have to override all component methods to define a new component. You only override the methods required to implement the functionality of your component. If you create a subclass of an existing component, such as Button control or VBox container, you must implement the methods necessary for you to add any new functionality to the component.

For example, you can implement a custom Button control that uses a new mechanism for defining its default size. In that case, you only need to override the measure() method. For an example, see Implementing the measure() method for MX components.

Or you might implement a new subclass of the VBox container. Your new subclass uses all of the existing sizing logic of the VBox class, but changes the layout logic of the class to lay out the container children from the bottom of the container to the top, rather than from the top down. In this case, you only need to override the updateDisplayList() method. For an example, see Implementing the updateDisplayList() method for MX components.

About interfaces

Flex uses interfaces to divide the basic functionality of components into discrete elements so that they can be implemented piece by piece. For example, to make your component focusable, it must implement the IFocusable interface; to let it participate in the layout process, it must implement ILayoutClient interface.

To simplify the use of interfaces, the UIComponent class implements all of the interfaces defined in the following table, except for the IFocusManagerComponent and IToolTipManagerClient interfaces. However, many subclasses of UIComponent implement the IFocusManagerComponent and IToolTipManagerClient interfaces.

Therefore, if you create a subclass of the class or subclass of UIComponent, you do not have to implement these interfaces. But, if you create a component that is not a subclass of UIComponent, and you want to use that component in Flex, you might have to implement one or more of these interfaces.

Note: For Flex, Adobe recommends that all of your components extend the UIComponent class or a class that extends UIComponent.

The following table lists the main interfaces implemented by Flex components:

Interface

Use

IAdvancedStyleClient

Indicates that the component supports the advanced style subsystem.

IAutomationObject

Indicates that a component is an object within the automation object hierarchy.

IChildList

Indicates the number of children in a container.

IConstraintClient

Indicates that the component support layout constraints.

IDeferredInstantiationUIComponent

Indicates that a component or object can effect deferred instantiation.

IFlexDisplayObject

Specifies the interface for skin elements.

IFlexModule

indicates that the component can be used with module factories

IInvalidating

Indicates that a component or object can use the invalidation mechanism to perform delayed, rather than immediate, property commitment, measurement, and drawing or layout.

ILayoutManagerClient

Indicates that a component or object can participate in the LayoutManager's commit, measure, and update sequence.

IPropertyChangeNotifier

Indicates that a component supports a specialized form of event propagation.

IRepeaterClient

Indicates that a component or object can be used with the Repeater class.

IStateClient

Indicates that the component supports view states.

IToolTipManagerClient

Indicates that a component has a toolTip property, and therefore is monitored by the ToolTipManager.

IUIComponent

Defines the basic set of APIs that you must implement in order to be a child of layout containers and lists.

IValidatorListener

Indicates that a component can listen for validation events, and therefore show a validation state, such as a red border and error tooltips.

IVisualElement

Indicates that the component can be laid out and displayed in a Spark application.