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

Gumbo ItemsComponent and Selector - Functional and Design Specification


Summary and Background


ItemsComponent is the base class for all skinnable components that have content. For example, Panel is a subclass of ItemsComponent that has a border, header, and footer. This is a pure model class that does not make any assumptions about the presentation or behavior of the items.

Selector is a subclass of ItemsComponent that is the base class for any skinnable component that supports selection. List, TabBar, ComboBox, and RadioButtonGroup are all subclasses of Selector. Selector is also a pure model class.

Usage Scenario


The ItemsComponent and Selector classes are not typically instantiated using MXML. These classes are primarily used as a base class for a new component, or as a SkinPart.

The first example extends ItemsComponent. The second example has a SkinPart that is typed as Selector.

Example 1: Panel Component

public class Panel extends ItemsComponent {

    // The content, layout, and itemRenderer properties are inherited from ItemsComponent. 
    // These are the main content for the Panel. 

    // Skin parts. The Panel class has two new parts: headerGroup and footerGroup. These
    // correspond to the header/footer of the Panel. The contentGroup part represents the
    // main content area.

    [SkinPart(required="false")]
    public var headerGroup:Group;

    [SkinPart(required="false")]
    public var footerGroup:Group;

    // Content for the header and footer
    public var header:*;
    public var footer:*;

    // This function is called when the skin part is loaded and assigned. 
    override protected function partAdded(partName:String, instance:*):void
    {
        // Assign the content to the header and footer. The main content
        // assignment is done in the superclass (ItemsComponent)
        switch (partName)
        {
            case "headerGroup":
                headerGroup.content = header;
                break;

            case "footerGroup":
                footerGroup.content = footer;
                break;

            default:
                super.partAdded(partName, instance);
                break;
        }
    }
}

Example 2: Media Browser

public class MediaBrowser extends SkinnableComponent {
    
    // The MediaBrowser can switch between Music, Photos, and Video. 
    // The component implementation doesn't care how the switching is 
    // done. It could be a set of tabs, a combobox, or a set of radio buttons;
    // as long as it is a subclass of Selector.
    [SkinPart]
    public var mediaTypeSelector: Selector;

    private static const mediaTypes:Array = ["Music", "Photos", "Video"];

    override protected function partAdded(partName:String, instance:*):void
    {
        if (instance == mediaTypeSelector)
        {
            // Set the content of the type selector
            mediaTypeSelector.content = mediaTypes;

            // Add a selectionChanged listener to the selector
            mediaTypeSelector.addEventListener("selectionChanged", 
                  mediaTypeSelector_selectionChangedHandler);
        }
        else
        {
            super.partAdded(partName, instance);
        }
    }

    private function mediaTypeSelector_selectionChangedHandler(event:Event):void
    {
        // Show the selected media
        showMedia(mediaTypeSelector.selectedItem);
    }
 
    private function showMedia(mediaType:String):void
    {
        ...
    }
}

Detailed Description


ItemsComponent

The ItemsComponent class is basically a skinnable Group. It has one SkinPart named contentGroup, and it proxies the content, layout, and item renderer functionality of the contentGroup skin part. See the API Description section for details.

Selector

The Selector class is a subclass of ItemsComponent that supports simple single selection. Multiple selection is handled in a subclass.

API Description


ItemsComponent

Most of the ItemsComponent APIs are proxies to the contentGroup skin part. Details on these APIs can be found in the Gumbo Group Spec.

package flex.component
{

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

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

[DefaultProperty("content")]

class ItemsComponent extends SkinnableComponent
{
    //--------------------------------------------------------------------------
    //
    //  Skin Parts
    //
    //--------------------------------------------------------------------------

    /**
     *  The Group that displays the content of this component. The content,
     *  layout, itemRenderer, and itemRendererFunction properties of the 
     *  component are assigned to this skin part.
     */
    [SkinPart]
    public var contentGroup:Group;

    //--------------------------------------------------------------------------
    //
    //  Group property and method proxies
    //
    //  The remainder of the ItemsComponent API are direct proxies to the 
    //  contentGroup SkinPart.
    //
    //  Details for these APIs can be found in the Group class.
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    public var content;
    public var layout;
    public var itemRenderer;
    public var itemRendererFunction;


    //--------------------------------------------------------------------------
    //
    //  Content management 
    //
    //  These are proxies to the properties and methods on the contentGroup
    //  skin part, provided for convenience. They are equivalent to accessing 
    //  the contentGroup part directly. For example, addItem(item); and 
    //  contentGroup.addItem(item); do the same thing. 
    //--------------------------------------------------------------------------

    public function get numItems();
    public function getItemAt();
   
    public function addItem();
    public function addItemAt();

    public function removeItem();
    public function removeItemAt();

    public function getItemIndex();
    public function setItemIndex();

    public function swapItems();
    public function swapItemsAt();
}

}

Selector

package flex.component {

/**
 *  Dispatched when the selection is going to change. Calling preventDefault()
 *  on the event will prevent the selection from changing.
 */
Event(name="selectionChanging", type="mx.events.IndexChangeEvent")]

/**
 *  Dispatched after the selection has changed. 
 */
[Event(name="selectionChanged", type="mx.events.IndexChangeEvent")]

public class Selector extends ItemsComponent
{
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    /**
     *  The 0-based index of the selected item, or -1 if no item is selected.
     *  Setting the selectedIndex property de-selects the currently selected
     *  item and selects the item at the specified index.
     *
     *  The value of selectedIndex is always pinned between -1 and 
     *  (numItems - 1). If items at a lower index than selectedIndex are 
     *  removed from the component, the selected index is adjusted downward
     *  accordingly. If the selected item is removed, selected index is
     *  set to -1 (if requireSelection = false or there are no remaining items) 
     *  or 0 (if requireSelection = true and there is at least one item).
     *
     *  @default -1
     */
    public var selectedIndex:int;

    /**
     *  The item that is currently selected. Setting the selectedItem property
     *  de-selects the currently selected item and selects the specified item.
     *
     *  Setting selectedItem to an item that is not in this component results in
     *  no selection, and selectedItem being set to undefined. If the selected 
     *  item is removed, the selected item is set to undefined (if requireSelection
     *  = false or there are no remaining items) or the first item (if 
     *  requireSelection = true and there is at least one item).
     *
     *  @default undefined
     */
    public var selectedItem:*;

    /**
     *  Specifies whether an item must always be selected.
     *  If the value is true, the selectedIndex property will always be
     *  set to a value between 0 and (numItems - 1), or -1 if there are
     *  no items.
     *
     *  @default false
     */
    public var requiresSelection:Boolean = false;

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Called when an item is selected or de-selected. Subclasses must override
     *  this method to display the selection.
     */
    protected function itemSelected(item:Object, selected:Boolean):void;
}

}

Prototype Work


Very basic implementations of ItemsComponent and Selector have been prototyped and checked in.

Compiler Work


None.

Web Tier Compiler Impact


None.

Flex Feature Dependencies


Group - ItemsComponent has a very tight connection with the Group class, and must keep the API's in sync.

ItemsComponent and Selector are the base class for numerous components. As these components are developed, some core functionality may be pushed back down into these classes.

Backwards Compatibility


Syntax changes

None. These are new classes.

Behavior

None. These are new classes.

Warnings/Deprecation

None.

Accessibility


The selectionChanged event will be the main accessibility hook for Selector. Due to the abstract nature of an item, we may need a general mechanism for determining the item type, and passing the item label to the accessibility implementation.

Performance


These classes are bound by the performance of the Group class.

Globalization


Not Applicable.

Localization


Compiler Features

None.

Framework Features

None.

Issues and Recommendations


Should the selection mechanism be moved to a separate object? The current thinking is single-selection is provided by the Selector class and multiple selection is provided by the List class. Are there other classes that need the concept of a selection?

QA


These are base classes, so testing should be API-focused.


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.

It might be nice if a selection was able to be applied to any set of items in a Group. For example if I didn't want to use a list but rather just make some Group that had an unknown number of content items and allow a single or multiple selection to be managed, it might be nice to have the Selection class(es) available for such a thing.

It might also be nice if I can take a selection from one List/Group/Whatever and then assign it to another and have it be applied if the same items where in there. Perhaps something like this would be useful for binding?

Just throwing out ideas to hopefully get some conversations started here! Thanks!

Thanks for the feedback, Shawn.

The Selector class is designed to be generic enough to use for any arbitrary selection on any arbitrary set of items. It is up to subclasses of Selector to interpret the selection, and it is up to the skins to display the selection. We considered having a separate selection class, but couldn't come up with enough real-world scenarios to justify the overhead (and complexity) of having selection be separated.

For your second scenario, you should be able to bind the selection between any two Selector/List classes.

Glenn
Adobe

 
Last Modified: 2008-07-14 11:34:36.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