Adobe Open Source
   Home     Projects     Source     Documentation     Forums    About
Welcome Guest | Sign In
 

Gumbo Group - Functional and Design Specification


Glossary


graphic element - A graphical item like a Rectangle, Path, or Bitmap. This element may not be a subclass of DisplayObject.
visual element - A visual item. This can be a component or a graphic element.
data element - A non-visual item like a String, Number, XMLNode, etc.

Summary and Background


Group is the simple container base class in Gumbo. It is designed to be both flexible and lightweight.

Groups can contain both visual and data elements. Layout is handled by a separate layout object.

Halo manages layout and containment differently in Container, ListBase, and individual components. In Gumbo, the Group class is used in all of these places, providing a single consistent mechanism for all layout in an application.

There are several key differences between the Group class and the Halo Container class:

  • Swappable layouts. In Group, layout is handled by a separate object. In Container, layout is baked into the Container subclass.
  • Looser requirements on children. Container required all content children to implement IUIComponent. Group allows any type of child, even raw data.
  • Group does not have any chrome, rawChildren or contentPane. If you want a border around a Group, it must be composited together separately.
  • Group does not automatically show scrollbars. Scrolling is handled in a separate subclass.
  • Group uses the faceless mechanism for deferred instantiation, and does not use UIComponentDescriptors.

The flex.core.Group class merges and supersedes the flex.core.ContentHolder and mx.graphics.Group classes.

Usage Scenario


Example 1: Button Skin

<Skin xmlns...>

    <!-- This group is the background graphics for the button skin. -->
    <Group left="0" right="0" top="0" bottom="0">
        <Rect radiusX="4" radiusY="4" left="0" top="0" right="0" bottom="0">
            <stroke> ... </stroke>
            <fill> ... </fill>
        </Rect>
        <Rect radiusX="3" radiusY="3" left="1" top="1" right="1" bottom="1">
            <fill> ... </fill>
        </Rect>
    </Group>

    <Label horizontalCenter="0" verticalCenter="0" text="{component.label}" />
</Skin>

Example 2: Panel Skin

<Skin xmlns...>

    <!-- This group is the header for the panel. Note that the "content"
         property for this group is bound to the "header" property of the Panel.
         Since Group content can be visual or data, this allows any arbitrary
         content to be inside a Panel header. -->
    <Group id="header" left="0" right="0" top="0" height="30"
           layout="flex.layout.HorizontalLayout" 
           content="{component.header}" />

    <!-- This group is the main content area for the panel. -->
    <Group id="content" left="5" top="35" right="5" bottom="35"
           layout="flex.layout.VerticalLayout"
           content="{component.content}" />

    <!-- This group is the footer for the Panel. -->
    <Group id="footer" left="0" right="0" bottom="0" height="30"
           layout="flex.layout.HorizontalLayout" 
           content="{component.footer}" />
</Skin>

Example 3: Simple List Skin

<!-- This is the item renderer definition. The group data item
     is bound into the renderer. -->
MyItemRenderer.mxml
<Group layout="flex.layout.HorizontalLayout">
    <Label text="{data.lastName}, {data.firstName}" />
    <Image source="{data.imageURL}" />
</Group>

<!-- This group contains raw data content. It uses an itemRenderer to
     display the data. -->
<Group itemRenderer="MyItemRenderer">
    <Object firstName="Chet" lastName="Haase" imageUrl="http://..." />
    <Object firstName="Corey" lastName="Lucier" imageUrl="http://..." />
    <Object firstName="Ely" lastName="Greenfield" imageUrl="http://..." />
    <Object firstName="Evtim" lastName="Georgiev" imageUrl="http://..." />
    <Object firstName="Glenn" lastName="Ruehle" imageUrl="http://..." />
</Group>

Detailed Description


Content

The default property of Group is content. The type is Object, which means any value can be assigned to it. The Group class supports single objects, Array, Vector, and classes that implement IList.

Content items can be any type of object. Group creates a visual representation, if needed, for each content item.

Here are the presentation rules:

  1. IDeferredInstance - Instance is instantiated. The instantiated object falls through to the next rule(s).
  2. DisplayObject - used directly. This includes any DisplayObject, not just classes that implement IUIComponent.
  3. IGraphicElement - used directly. Group calls the draw() method on the element when needed.
  4. If itemRendererFunction is defined, call it to get the renderer for the item
  5. If itemRenderer is defined, instantiate one
  6. Finally, if no visual item is found, use Label (or equivalent Gumbo component) and call toString() on the item

When the value of the content property is an Array or Vector, the content APIs must be used to manipulate the content items, and the content property should only be used to initialize or reset all content items. The APIs mimic the child management APIs in DisplayObjectContainer.

When the value of the content property is an IList, content items can be manipulated using either the content APIs on Group, or the item APIs on IList.

You can use the DisplayObjectContainer numChildren and getChildAt() APIs to iterate the visual children. The APIs that add, remove or shuffle children should not be called, and will throw an RTE if they are called.

Item Renderers

An item renderer is created for each data element in a Group. This renderer is the visual representation of the data element.

The itemRenderer property specifies an IFactory that is used to instantiate an instance of a renderer. The renderer must implement the IDataRenderer interface. The item is assigned to the data property of the renderer.

The itemRendererFunction property is used to specify a callback function that returns an item renderer for a specific piece of data. The function is passed an item and returns an IFactory that is used to create the renderer.

Example: itemRendererFunction

private function myItemRendererFunction(item:*):IFactory
{
// "employee" and "contractor" get special renderers.
if (item.status == "employee")
return employeeItemRenderer;
else if (item.status == "contractor")
return contractorItemRenderer;

// everyone else gets the default renderer.
return defaultItemRenderer;
}

The alwaysUseItemRenderer property is used to force an item renderer to be created for each item, even if the item is already a visual element. The default value for alwaysUseItemRenderer is false.

Graphic Elements

The Group class supports graphic elements as content. Group is responsible for allocating backing display objects when needed, and calling the draw() method on the graphic elements. The Group class supports all of the attributes of the FXG Group tag described in the FXG 1.0 specification.

Layout

Layout and measurement are handled by a separate object, which can be changed dynamically at runtime. Details about layout management will be handled in a separate spec. For now, the important parts to know are:

  • Measurement and layout are done by the layout object, not the Group
  • Custom layouts can be written
  • Basic layouts are very simple. Most likely, there will be a single instance that is shared among all Groups.
  • There will be a mechanism for setting layout-specific properties for a component (eg horizontalGap).

Clipping and Scrolling

Basic rectangular clipping and pixel-based scrolling is supported by the DisplayObject scrollRect property. Masking is supported by the DisplayObject mask property.

Display and management of scrollbars must be done by a subclass or external controller class.

API Description


package flex.core
{

/**
*  Dispatched prior to the group's content being changed. This is only
*  dispatched when all content of the group is changing.
*/
[Event(name="contentChanging", type="flash.events.Event")]

/**
*  Dispatched after the group's content has changed. This is only
*  dispatched when all content of the group has changed.
*/
[Event(name="contentChanged", type="flash.events.Event")]

/**
*  Dispatched when an item is added to the Group.
*  event.relatedObject is the item that was added.
*/
[Event(name="itemAdd", type="flex.events.ItemExistenceChangedEvent")]

/**
*  Dispatched when an item is removed from the Group.
*  event.relatedObject is the item that was removed.
*/
[Event(name="itemRemove", type="flex.events.ItemExistenceChangedEvent")]

class Group extends UIComponent implements IGraphicElementHost
{
//--------------------------------------------------------------------------
//
//  Properties
//
//--------------------------------------------------------------------------

/**
*  Flag that specifies whether or not an item renderer should always be
*  created for each item. When true, an item renderer is always created
*  for each item, even if the item is a visual element.
*
*  @default false
*/
public var alwaysUseItemRenderer:Boolean;

/**
*  Content for this Group.
*
*The content can be an Array, Vector, IList, or
*  a single item. The content items can be any type.

*
*  @default undefined
*
*  @see #itemRenderer
*  @see #itemRendererFunction
*/
public function get content():*;
public function set content(value:*):void;

/**
*  Renderer to use for data items. The class must
*  implement theIDataRendererinterface.
*  TheitemRendererFunctionproperty,
*  if defined, takes precedence over this property.
*
*  @default null
*/
public var itemRenderer:IFactory;

/**
*  Function that returns an item renderer for a specific item.
*  The signature of the function is:

*function itemRendererFunction(item:*):IFactory
*
*  @default null
*/
public var itemRendererFunction:Function;

/**
*  Layout for this Group.
*
*The layout object is responsible for measurement
*  and layout of the Group contents.

*
*  @default flex.layout.BasicLayout
*
*  @see ILayout
*/
public function get layout():Class;
public function set layout(value:Class):void;

//--------------------------------------------------------------------------
//
//  Content management
//
//  The properties and methods in this section mimic the child management
//  APIs available in the flash class DisplayObjectContainer.
//
//--------------------------------------------------------------------------

//----------------------------------
//  Item iteration
//----------------------------------

/**
*  The number of items in this group.
*
*  @return The number of items in this group
*/
public function get numItems():int;

/**
*  Gets thenth item in the Group.
*
*  @param index The index of the item to retrieve.
*
*  @return The item at the specified index, or null if the item does not exist.
*/
public function getItemAt(index:int):*;

//----------------------------------
//  Item addition
//----------------------------------

/**
*  Adds an item to this Group. The item is added after all other
*  items.
*
*  @param item The item to be added to the Group.
*
*  @return The item that was added to the Group.
*/
public function addItem(item:*):*;

/**
*  Adds an item to this Group. The item is added at the index
*  specified.
*
*  @param item The item to be added to the Group.
*  @param index The index to add the item at.
*
*  @return The item that was added to the Group.
*/
public function addItemAt(item:*, index:int):*;

//----------------------------------
//  Item removal
//----------------------------------

/**
*  Removes an item from this Group.
*
*  @param item The item to be removed from the Group.
*
*  @return The item removed from the Group.
*/
public function removeItem(item:*):*;

/**
*  Removes an item at a specified index from this Group.
*
*  @param index The index of the item to remove.
*
*  @return The item removed from the Group.
*/
public function removeItemAt(index:int):*;

//----------------------------------
//  Item index
//----------------------------------

/**
*  Gets the zero-based index of a specific item.
*
*  @param item Reference to item whose index to get.
*
*  @return Number between 0 and (numItems - 1), or -1 if
*          the item is not in this Group.
*/
public function getItemIndex(item:*):int;

/**
*  Sets the zero-based index of a specific item.
*
*  @param item The item whose index is being set.
*  @param index The new zero-based index for the item.
*/
public function setItemIndex(item:*, index:int):void;

//----------------------------------
//  Item swapping
//----------------------------------

/**
*  Swaps the index of the two specified items. All other items
*  remain in the same index position.
*
*  @param item1 The first item.
*  @param item2 The second item.
*/
public function swapItems(item1:*, item2:*):void;

/**
*  Swaps the index of the two specified items. All other items
*  remain in the same index position.
*
*  @param index1 The index of the first item.
*  @param index2 The index of the second item.
*/
public function swapItemsAt(index1:int, index2:int):void;

//--------------------------------------------------------------------------
//
//  Content to renderer mapping
//
//--------------------------------------------------------------------------

/**
*  Returns the instance of the renderer for the specified item. If the
*  the specified item is a visual item (component or IGraphicElment),
*  the item itself is returned.
*
*  @param item The item whose renderer is to be returned.
*
*  @return The renderer instance for the specified item. If the item
*          is a subclass of DisplayObject or IGraphicElement, the item
*          itself is returned.
*/
public function getItemRenderer(item:*):*;

/**
*  Returns the item associated with the specified renderer.
*
*  @param renderer The renderer whose item you want to retrieve.
*
*  @return The item associated with the specified renderer.
*/
public function getRendererItem(renderer:*):*;

//--------------------------------------------------------------------------
//
//  Layout item iteration
//
//  Iterators used by Layout objects. For visual items, the layout item
//  is the item itself. For data items, the layout item is the item renderer
//  instance that is associated with the item.
//
//--------------------------------------------------------------------------

/**
*  The number of layout items in this Group. Typically this is the same
*  as the number of items in the Group.
*/
public function get numLayoutItems():int;

/**
*  Gets thenth layout item in the Group. For visual items, the
*  layout item is the item itself. For data items, the layout item is the
*  item renderer instance that is associated with the item.
*
*  @param index The index of the item to retrieve.
*
*  @return The layout item at the specified index.
*/
public function getLayoutItemAt(index:int):Object;

//--------------------------------------------------------------------------
//
//  Protected methods
//
//--------------------------------------------------------------------------

/**
*  Create the visual representation for the item, if needed.
*
protected function createVisualForItem(item:*):DisplayObject;

/**
*  Called when an item has been added to this Group.
*
*  @param item The item that was added.
*  @param index The index where the item was added.
*/
protected function itemAdded(item:*, index:int):void;

/**
*  Called when an item is about to be removed from this Group.
*
*  @param index The index of the item that is being removed.
*/
protected function itemRemoved(index:int):void;
}

}

B Features


None at this time.

Compiler Work


None required.

Web Tier Compiler Impact


Not Applicable.

Flex Feature Dependencies


States - The new enhanced states syntax supports adding and removing items from a Group. This work is encapsulated in the AddItems/RemoveItems override tags, and has already been completed.

Layout - There is obviously a tight relationship between layout objects and Group. Refer to the Layout specification for more information.

Focus - Group is not focusable, but items within the group must be able to receive focus.

Styles - Group does not have styles, but can be a style parent (either direct or proxy) for the items within the group.

Virtualization - This will most likely be done as a subclass of Group.

Backwards Compatibility


Syntax changes

None. This is a new class.

Behavior

None, for existing content. For new content, there are some fundamental differences between Group and the old mx:Container class that need to be understood.

Warnings/Deprecation

None.

Accessibility


None, directly. The Group class itself does not have any accessibility features, but it does need to support accessibility of its children.

Performance


Size and speed are both critical elements of the Group class. A typical application may end up with thousands of Group objects at runtime, so performance testing must be done early and often.

Globalization


None. Right to left or vertical orientation is handled by the various layout classes, and does not require any specific functionality from Group.

Localization


Compiler Features

Not applicable.

Framework Features

List the RTE message strings that will require localization. (They must all come from .properties files.)

RTE messages are displayed when calling the Flash DisplayObjectContainer children APIs directly - addChild()/removeChild()/etc.

List all UI text that will require localization, such as the month and day names in a DateChooser. (All such text must all come from .properties files.)

None.

List all UI images, skins, sounds, etc. that will require localization.

None.

Discuss any locale-specific formatting requirements for numbers, dates, currency, etc.

None.

Discuss any locale-specific sorting requirements.

None.

Issues and Recommendations


Supporting scale grid properties on Group. The FXG Group tag supports the properties scaleGridLeft, scaleGridTop, scaleGridRight, and scaleGridBottom. We need to support these properties too. One solution is having these properties automatically assign the "ScalingLayout" to the Group.

Make group a non-DisplayObject. Since there are so many Group objects in any given application, it would be great if they weren't all required to be DisplayObjects. Early prototyping proved a noticeable increase in startup time and decrease in overall memory usage, but many details would need to be worked out.

Extensible data support. Group has basic support for IList, but does not directly support paging data sets. Ideally, this could be layered on with either a subclass or an intermediate proxy object that implements IList.

QA


Yes

Flex SDK Project
Home
About
Versions
Downloads
Source
Bug Database
Submitting a Patch
Developer Documentation
Forums
License

Pages
Comments

Other Projects
BlazeDS
Cairngorm
Corelib
FlexUnit

More related projects ›
More Adobe projects ›
You must be logged in to comment.

Just want to comment and add how important scaling support is. I recently came across an interesting bug in Flex that does not exist in Flash. In Flex it is impossible to scale a flash.text.TextField in way that is not proportional, if you change the scale of y either from scaleY or the matrix, it updates the scale of x and vice versa. This works fine in Flash, but not Flex. Very odd. I even tried going as far as creating a MovieClip in Flash with a TextField in it and embedding it in Flex to use.

How does this fit in with the existing Container class? Does the Group class handle keyboard tab loops? Will the Container class subclass Group?

Group is the Gumbo replacement for Container. Container will not be a subclass of Group.

Yes, Group does handle keyboard tab loops.

 
Last Modified: 2008-07-14 11:34:04.0
Powered by Atlassian Confluence 2.7.1, the Enterprise Wiki.

Company | Online Privacy Policy | Terms of Use | Contact Us | Accessibility | Report Piracy | Permissions & Trademarks

Copyright @ 2008 Adobe Systems Incorporated.
Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.
Search powered by Google