Flex 3 Anatomy

Anatomy of the Flex 3 Framework.

Introduction to the Flex 3 Anatomy

The Flex SDK is a large body of code that Adobe has released under an open source license. Reading the Flex source code is one of the best habits to develop as a Flex developer. The code provides insight into what Adobe engineers were thinking during development and how they expect their components to be used. The code is also intended as a blueprint for implementing your own components.

Of course, not everything is idyllic in the Flex SDK. There are many bad practices and frustrations to be found also. The Anatomy will dissect the Flex SDK and expose its workings. It will examine the design decisions of the authors, the API, inheritance, interfaces, and function of the code.

Major topics will include:

The Flex 3 Class Hierarchy

Understanding the Flex 3 class hierarchy is the first step to grasping the Flex source code. Much of the Flex code is shared in key parent classes and it is important to understand this structure before delving into the details of a particular class in the framework.

The Flex 3 class hierarchy extends from various parent classes which begin with the name Flex* such as FlexSprite and FlexShape, which are subclasses of Sprite and Shape, respectively. These classes are very small and simply change the semantics of the name property to correspond to Flex's idea of the display list. For more about Sprite and Shape, see the Flash Physiology. From FlexSprite, the hierarchy goes to UIComponent which is the base class for all of the interactive classes in Flex.

UIComponent is the parent of the basic visual components such as Button, CheckBox, and ComboBox, as well as the parent of the more complicated classes such as Canvas, DataGrid, and Tree. UIComponent is such a monolithic class that it has its own section in the Anatomy.

FlexShape is the parent of non-interactive Flex components. This is limited to ProgrammaticSkin, which is the parent of Border and then RectangularBorder. See the section on Skinning for more details on these classes.

UIComponent - the core of Flex 3

UIComponent is the core class in Flex 3 for all of the interactive classes. Its class hierarchy is UIComponent < FlexSprite < Sprite < DisplayObjectContainer < InteractiveObject < DisplayObject. A UIComponent can render graphics using the drawing API (from Sprite), have other DisplayObjects as children (from DisplayObjectContainer) and supports mouse and keyboard interaction (from InteractiveObject). But the real work in UIComponent is in basic Flex functionality it implements.

UIComponent defines the core interaction of the Flex 3 component model such as styles, tooltips, validators, states, repeaters, invalidation, measuring, layout, and rendering. The Flash classes such as Sprite do not follow these standards and are not constrained and supported by the Flex component model. This is an important consideration when choosing a base class for custom components.

More to come..

UIComponent events

updateComplete Flex Event

The updateComplete event is dispatched from all UIComponents after they have been through the validation phase in the rendering lifecycle. It is called after the commitProperties(), measure(), and updateDisplayList() methods have been called.

This method will only be called when the component is invalidated. Some components will not be invalidated very often during their lifecycle if their size is constant and they do not perform rendering updates or have their properties changing. Other components, however, will dispatch this event quite often as they respond to user input or other events to update themselves.

The updateComplete event is not actually dispatched from code inside UIComponent, however. It is dispatched from the LayoutManager after it has completed validating the UIComponent.

The event is dispatched during phased and non-phased instantiation after all the phases have been completed in the private function doPhasedInstantiation():

  1.       while (obj)
  2.       {
  3.         if (!obj.initialized && obj.processedDescriptors)
  4.           obj.initialized = true;
  5.         obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
  6.         obj.updateCompletePendingFlag = false;
  7.         obj = ILayoutManagerClient(updateCompleteQueue.removeLargest());
  8.       }
  9.  
  10.       // trace("updateComplete");
  11.  
  12.       dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));

This method is the core lifecycle method for components in Flex. The LayoutManager uses phased instantiation during the initial load of your application and will then disable it after it is complete. You can also see that LayoutManager dispatches this event on itself after all components have been updated (some components such as UIComponent and Container listen for this).

The updateComplete event will also be dispatched for a UIComponent when the validateNow() method is called.

Advanced Data Visualization components

AdvancedDataGrid Flex class

The AdvancedDataGrid is a new class available in Flex 3 as part of the data visualization package. You can experiment with the AdvancedDataGrid without owning the correct license, but you'll get a watermark above every grid.

The AdvancedDataGrid adds many features to the DataGrid. Actually, the AdvancedDataGrid is so different, it does not inherit from DataGrid, as you might expect. The DataGrid inheritance is DataGrid < DataGridBase < ListBase < ScrollControlBase. For the AdvancedDataGrid it goes AdvancedDataGrid < AdvancedDataGridBaseEx < AdvancedDataGridBase < AdvancedListBase < ScrollControlBase. Just as ListBase is the basis for the basic lists such as List, DataGrid, and TileList, AdvancedListBase serves as the base class for AdvancedDataGrid and OLAPDataGrid.

The AdvancedDataGrid exposes a property called hierarchicalCollectionView which is a HierarchicalCollectionView. This is typically identical to the dataProvider property (except in cases where you set the dataProvider to a HierarchicalCollectionView yourself). Internally, the AdvancedDataGrid accesses its dataProvider by casting its protected collection:ICollectionView property (from AdvancedListBase) to an IHierarchicalCollectionView.

If you want to filter the data, you need to apply your filter to this property. Filters applied to the source of the HierarchicalData will not work as expected. There is a Solution about Filtering HierarchicalCollectionViews that will help, as will reading the article on HierarchicalCollectionView.

More to come...

HierarchicalCollectionView Flex class

The HierarchicalCollectionView class is part of the advanced data visualization components that come with Flex Builder 3 Professional. It is used by the AdvancedDataGrid to represent a view of a hierarchical collection. This class includes functionality to construct a hierarchy; to open and close nodes; to apply filters and sorts; to iterate through the hierarchy; to monitor the data for changes; and to query the visible state of the data.

There is another class in the Flex SDK called HierarchicalCollectionView (in mx.controls.treeClasses) that is used internally by the Tree class. I will work out how to disambiguate the terms later. At the moment, I don't have an entry for that class.

I cannot publish the source code for this class because it is part of the proprietary data visualization components that Adobe sells as part of Flex Builder 3. I will be explaining some aspects of the internal behavior of the class, just without the accompanying source code.

This class is intimately tied to the AdvancedDataGrid. The HierarchicalCollectionView takes care of managing the hierarchy and communicates to the AdvancedDataGrid primary through event propagation. It is used to wrap the data in a HierarchicalData instance, in XML, or in a GroupingCollection.

As explained in the Solution Filter HierarchicalCollectionView parent and child branches, you can apply a filter function to the view and it will be applied to all of the items in the hierarchy from the top down. Sorts are similarly applied to all collections which comprise the hierarchy in a descending manner. If you have modeled your data using HierarchicalData, then it will sort parents and children separately. The GroupingCollection actually builds a similar hierarchy of ArrayCollections out of your flat data when you call refresh(), so it will behave in the same manner.

More to come...

Container Classes

The Container classes in Flex are designed to hold other components and perform positioning and sizing on their behalf. The Container class itself implements many of the necessary operations for the child classes. Container extends UIComponent and adds a significant amount of additional functionality. Often, if you are searching for the root behavior of one of the specific subclasses you will find that the code actually resides in Container.

The Container class has a major piece of functionality that deals with how it lays out its children. Normally, the children of a DisplayObjectContainer or UIComponent are direct children of the component. However, the children of a Container may be moved from direct to children to grandchildren by means of the contentPane property/child. This topic is dealt with in detail in the contentPane article.

Container Flex Class

The Container class implements much of the behavior of the containers in the Flex Framework. This article is broken into sections to deal with each of the pieces of functionality individually.

The contentPane of Container

The contentPane property of the Container class allows Container to turn its children into grandchildren and therefore allow them to render separately from other children (such as scrollbars) which may need to live alongside them.

The Container class may or may not move its children into the contentPane. Whether it does this is based on a number of complicated (and likely to change) rules. The most obvious rule, as seen in the private function createContentPaneAndScrollbarsIfNeeded() is to handle scrollbars properly. The contentPane property stands in opposition to the rawChildren property which allows direct access to children of the Container which may be part of the chrome of the display (such as the border of a Panel).

One problem this can cause is the unhelpful firing of the removedFromStage or removed event for components which are children of a Container. Of course, nearly every Flex project has some Containers in its hierarchy. When the Container determines it must create the contentPane, it calls the mx_internal function createContentPane():void. The contentPane that is created is a FlexSprite:

  1.         var newPane:Sprite = new FlexSprite();
  2.         newPane.name = "contentPane";
  3.         newPane.tabChildren = true;

Then Container goes through its children one-by-one and moves them into the contentPane. This is where the removedFromStage event is dispatched to the child components. Calling addChild(child:DisplayObject) forces the child to be removed from its current parent first. The child will receive the removed event and, if the parent is on the display list, it will also receive the removedFromStage event.

  1.         for (var i:int = 0; i < n; i++)
  2.         {
  3.             // use super because contentPane now exists and messes up getChildAt();
  4.             var child:IUIComponent =
  5.                 IUIComponent(super.getChildAt(_firstChildIndex));
  6.             newPane.addChild(DisplayObject(child));
  7.             child.parentChanged(newPane);
  8.             _numChildren--; // required
  9.         }

This can be problematic if your component assumes that its lifetime is over when it is removed from the stage, because it will be instantly added back to the Stage in this case. In general, you have to assume that your component may be added to and removed from the Stage and the display list at any time and it should recover gracefully from such treatment. Unfortunately, at least one class in the Flex 3 Framework does not: PopUpButton.

List Classes

List classes are rooted in the ListBase class and include DataGrid and ListBase.

ListBase Flex Class

The ListBase class is the base class for all of the list classes in Flex which are:

List classes share a common interface through the dataProvider properties and they dispatch similar events.

More to come...

DataGrid

The DataGrid class is a very flexible and commonly used class that displays a set of data in a grid. This data is structured into rows and columns and the data can be edited.

DataGrid is a subclass of DataGridBase which extends ListBase. DataGridBase provides some of the default implementation of the DataGrid, but there are no other subclasses of DataGridBase.

More to come...

Skinning in Flex 3

Skinning in Flex 3.

States and Transitions

State Flex class

The State class is a small class that is really only used to define the states of a component. It inherits only from EventDispatcher. State has a three public properties: overrides:Array, basedOn:String, and name:String. overrides holds the operations that the State will perform when it is applied to a component. name sets the name of the state and basedOn established a hierarchy between states. The functionality for the State is implemented in UIComponent and the individual overrides, which all implement the IOverride interface.

The State class exposes three internal methods using the mx_internal namespace so that UIComponent can call them when it is applying states to itself. These methods are initialize(), dispatchEnterState(), and dispatchExitState().

initialize() simply loops through its child overrides, calling initialize() on them and then marking itself as initialized:

  1.     mx_internal function initialize():void
  2.     {
  3.       if (!initialized)
  4.       {
  5.         initialized = true;
  6.         for (var i:int = 0; i < overrides.length; i++)
  7.         {
  8.           IOverride(overrides[i]).initialize();
  9.         }
  10.       }
  11.     }

Each of the dispatch* methods simply perform a dispatchEvent() of the appropriate events. I don't know why the Adobe developers would add methods such as these because dispatchEvent() is a public method on EventDispatcher and UIComponent could just call this directly on the State (as it inherits from EventDispatcher). Perhaps they just wanted to encapsulate the functionality in case it would change in the future.

In the case where the UIComponent is returning to its base state, there is not an explicit State object associated with this state, so the UIComponent dispatches the enterState event on itself:

  1.         // If we're going back to the base state, dispatch an
  2.         // enter state event, otherwise apply the state.
  3.         if (isBaseState(currentState))
  4.             dispatchEvent(new FlexEvent(FlexEvent.ENTER_STATE));
  5.         else
  6.             applyState(_currentState, commonBaseState);

enterState Flex Event

The enterState event is dispatched from the State class when a new state has been entered. The class that actually dispatches this event is UIComponent. State is actually a very small class that exposes an mx_internal method dispatchEnterState() which UIComponent hijacks since it is in charge of applying states to itself:

  1.     private function applyState(stateName:String, lastState:String):void
  2.     {
  3.         var state:State = getState(stateName);
  4.  
  5.         if (stateName == lastState)
  6.             return;
  7.            
  8.         if (state)
  9.         {
  10.             // Apply "basedOn" overrides first
  11.             if (state.basedOn != lastState)
  12.                 applyState(state.basedOn, lastState);
  13.  
  14.             // Apply new state overrides
  15.             var overrides:Array = state.overrides;
  16.  
  17.             for (var i:int = 0; i < overrides.length; i++)
  18.                 overrides[i].apply(this);
  19.  
  20.             // Dispatch the "enterState" event
  21.             state.dispatchEnterState();
  22.         }
  23.     }

This code is called from commitCurrentState() which is also a private method in UIComponent.

Flex utility classes

NameUtil Flex utility class

The NameUtil class provides two methods for creating names for DisplayObjects. In particular, these two methods are used in FlexSprite and FlexShape to set the name property and the return value of toString().

UIDUtil Flex class

The UIDUtil class is a utility class for manipulating UIDs (universal identifiers) in Flex. A UID is a very unique String which is hopefully fully unique. The UID is intended to be a unique index to a particular instance of a class in Flex. The UIDUtil class has static methods that can create and fetch UIDs for any Object in a Flash application. UIDUtil is commonly used by the list classes to index their contents and provide lookups for various purposes.

The most commonly used method on UIDUtil is the public static getUID(item:Object):String method. It is worth looking at in full detail:

  1.     public static function getUID(item:Object):String
  2.     {
  3.         var result:String = null;
  4.  
  5.         if (item == null)
  6.             return result;

If the value passed in is null, then it is simply returned.

  1.         if (item is IUID)
  2.         {
  3.             result = IUID(item).uid;
  4.             if (result == null || result.length == 0)
  5.             {
  6.                 result = createUID();
  7.                 IUID(item).uid = result;
  8.             }
  9.         }

If the value passed in implements the IUID interface, then the uid property is inspected. If it is not set, then createUID() is called and the value is set. The method will return the result variable at the end.

  1.         else if ((item is IPropertyChangeNotifier) &&
  2.                  !(item is IUIComponent))
  3.         {
  4.             result = IPropertyChangeNotifier(item).uid;
  5.             if (result == null || result.length == 0)
  6.             {
  7.                 result = createUID();
  8.                 IPropertyChangeNotifier(item).uid = result;
  9.             }
  10.         }

This piece of code is a puzzle to me. If the item is an IPropertyChangeNotifier, and not an IUIComponent, then the code does the same as the above code for the IUID interface. This is puzzling because IPropertyChangeNotifier extends IUID, so any class that implements IPropertyChangeNotifier should have been handled by the first condition.

  1.         else if (item is String)
  2.         {
  3.             return item as String;
  4.         }

If the item is a String, then it is simply returned as is.

The next block handles XML and everything else. I'm not too familiar with the XML code, so I won't try to explain it all. Apparently there is a mechanism to perform notifications from XML objects and that mechanism will store a UID. Here is the code:

  1.                     var xitem:XML = XML(item);
  2.                     var nodeKind:String = xitem.nodeKind();
  3.                     if (nodeKind == "text" || nodeKind == "attribute")
  4.                         return xitem.toString();
  5.  
  6.                     var notificationFunction:Function = xitem.notification();
  7.                     if (!(notificationFunction is Function))
  8.                     {
  9.                         // The xml node hasn't already been initialized
  10.                         // for notification, so do so now.
  11.                         notificationFunction =
  12.                             XMLNotifier.initializeXMLForNotification();
  13.                         xitem.setNotification(notificationFunction);
  14.                     }
  15.  
  16.                     // Generate a new uid for the node if necessary.
  17.                     if (notificationFunction["uid"] == undefined)
  18.                         result = notificationFunction["uid"] = createUID();
  19.  
  20.                     result = notificationFunction["uid"];

The last block handles objects which haven't been handled elsewhere. First, it will check for a property called mx_internal_uid, then a property called uid, returning those if found:

  1.                     if ("mx_internal_uid" in item)
  2.                         return item.mx_internal_uid;
  3.  
  4.                     if ("uid" in item)
  5.                         return item.uid;

Lastly, it will attempt to lookup the object in an internal Dictionary and, if it can't find the object there, it will create a new UID and either put it into the mx_internal_uid property or into the Dictionary

  1.                     result = uidDictionary[item];
  2.  
  3.                     if (!result)
  4.                     {
  5.                         result = createUID();
  6.                         try
  7.                         {
  8.                             item.mx_internal_uid = result;
  9.                         }
  10.                         catch(e:Error)
  11.                         {
  12.                             uidDictionary[item] = result;
  13.                         }
  14.                     }

Notice the try..catch block. This block will add a new property to a dynamic class called mx_internal_uid. A dynamic class can have properties added and removed at runtime. Object and Array are dynamic classes, and you can declare your own dynamic class by including the dynamic keyword in your class declaration.

There is also a try..catch block that begins the final else and uses the results of calling toString() on the item if an exception is thrown:

  1.             catch(e:Error)
  2.             {
  3.                 result = item.toString();
  4.             }

The end of the method returns whatever value was assigned to result:

  1.         return result;

The other method of primary importance is the createUID() method which actually creates the UID. It does this by generating a string in the form "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" where X is a hexadecimal digit. The first four groups of characters are generated by this code:

  1.             uid[index++] = ALPHA_CHAR_CODES[Math.floor(Math.random() *  16)];

The last group is generated by grabbing the lowest 8 hexadecimal digits of the current timestamp (which is in milliseconds since 1970), and then 4 more random digits using the same method as above.

This algorithm will generate a UID that has a very good chance of being universally unique even among Flash player instances and servers. However, it is not as unique as a true GUID would be.

Lastly, I want to mention the internal Dictionary that stores the UIDs of instances that don't support storing the UID on them. This Dictionary is defined as:

  1.     private static var uidDictionary:Dictionary = new Dictionary(true);

The true parameter indicates that the Dictionary should store weak keys. This means that the references that the Dictionary keeps to your objects will be ignored for the sake of garbage collection. Also noticed that the Dictionary is static. This means that your Flash application will always return the same UID for a given instance over its lifetime, whether or not that instance stores the UID on itself or not.

Intermediary Flex classes

These classes mediate between Flash and Flex and provide some minor translation of the functionality of Flash into the functionality expected by Flex. FlexSprite and FlexShape translate the name property and toString() method into the expected behavior in Flex.

Both classes have essentially the same functionality. In their constructor, they perform an assignment such as this (from FlexSprite):

  1.       name = NameUtil.createUniqueName(this);

The createUniqueName NameUtil class creates a unique name based on the qualified class name of the object is is passed. It appends an incrementing number (stored in a static variable) to the name to ensure uniqueness.

Both FlexSprite and FlexShape trap this assignment in a try..catch block and silently fail if there is an error. This is explained in the comments because DisplayObjects placed on a Timeline cannot have their name property modified.

The toString() method is also overridden (from FlexSprite):

  1.     override public function toString():String
  2.   {
  3.     return NameUtil.displayObjectToString(this);
  4.   }

displayObjectToString in NameUtil loops through all of the DisplayObjectContainer parents of the FlexSprite and prepends them to the string with a dot between each name. It terminates at the Stage instance.

FlexShape Flex class

The FlexShape class is a very small class that extends the Flash Shape class and sets its name property to a unique identifier and overrides the toString() method to return a dot separated path to the Flash Stage.

The behavior is fully explained in the article on Intermediary Flex classes along with FlexSprite which has an identical implementation.

FlexSprite Flex class

The FlexSprite class is a very small class that extends the Flash Sprite class and sets its name property to a unique identifier and overrides the toString() method to return a dot separated path to the Flash Stage.

The behavior is fully explained in the article on Intermediary Flex classes along with FlexShape which has an identical implementation.