|
Jason Szeto (Dev) Functional and Design SpecificationGlossary | Changes from Original DropDownList Design | Summary and Background | Usage Scenarios | Detailed Description | API Description | B Features | Examples and Usage | Additional Implementation Details | Prototype Work | Compiler Work | Web Tier Compiler Impact | Flex Feature Dependencies | Backwards Compatibility | Accessibility | Performance | Globalization | Localization | Issues and Recommendations | Documentation | QA
GlossaryAnchor - the button or component that when pressed, opens the dropDown. dropDown component - general term referring to a component that contains an anchor button and a dropDown DropDownController - class that contains the user interaction logic for a dropDown component DropDownList - a dropDown component that consists of a labeled button and a List dropDown. dropDown - component that is displayed when the user presses the button of a dropDown component. dropDown animation - the visual effect that occurs when a dropDown is displayed or hidden. A common effect is to slide or zoom the dropDown into view. PopUpAnchor - Spark component that is used to position a dropDown in layout. Since a dropDown is added to the display list via the PopUpManager, it doesn't normally participate in layout. The PopUpAnchor component is a UIComponent that does get added to a container and thus is laid out. It is responsible for then sizing and positioning the dropDown relative to itself. Changes from Original DropDownList DesignThis is a revised version of the original spec. The main change is that DropDownList subclasses List instead of DropDownBase. DropDownBase has been removed and its functionality will be moved into a controller class that is used in each dropDown component class. Thanks go to Iwo Banas for his design suggestions. Since DropDownList subclasses List instead of DropDownBase, its skin no longer has a dropDown skin part. Instead, it inherits the dataGroup skin part from List. Summary and BackgroundDropDownList is an example of a broader category of components that we call button dropDown components. These components consist of a button with a label/icon and a dropDown component. Each dropDown component subclasses the class that is dropped down. For example, DropDownList subclasses List while DropDownSlider subclasses Slider. Examples of possible dropDown components:
Each dropDown component will contain a required button skin part. A controller class called DropDownController has logic for opening and closing the dropDown based on keyboard and mouse interactions with the button. The size and position of the dropDown is defined by the skin. The skin also provides animations when the dropDown is shown and hidden. DropDownList is a non-editable, selectable dropDown List with a labeled button. It subclasses List and adds the prompt property. It also modifies the user interaction behavior found in List. Usage ScenariosMick is creating an online survey for the PitchSpoon music site. One of the questions is to select the "Best Rock Band of All Time." Since the list of choices is long and he doesn't want to take too much screen real estate, he uses a DropDownList to capture the answer. He adds the DropDownList in his application, hooks up the dataProvider to his back end data. Mick decides to also add in a question for "Best Rock Album of All Time." He again decides to use a DropDownList. But he wants to enhance the experience by including a thumbnail of the album along with the title and band name. He creates an itemRenderer with the thumbnail on the left and on the right, the album title and band name. The itemRenderer is taller than the standard one line renderer. He doesn't want the DropDownList button to take up that much space, so he adds an Image tag and SimpleText into the skin to display the album cover and the title, using binding to populate the data. Flea is building a red hot music player. The design calls for small, minimal controls. He wants the user to be able to control the volume, but he doesn't have the space to put a slider control. Instead, he creates a dropDown Slider component. Since one is not included in the Spark component set, he needs to create a custom component. He creates DropDownSlider which subclasses Slider. He creates a custom skin which creates a button with an icon and a vertical track and thumb dropDown skin part. He incorporates a DropDownController instance to control the user interaction. He then includes an instance of his new class in his music player, being sure to pass in a volume icon to the DropDownSlider. This volume icon will be assigned to the button's icon property. Detailed DescriptionDropDownListThe DropDownList class extends List. It has an optional skin part called labelElement. This part is of type TextGraphicElement and its text property is always set to the selectedItem's string representation. The string representation is calculated by passing the data to the static List.itemToLabel function which takes a labelFunction, labelField and the data. The prompt property contains the text to display when the DropDownList has no selection. The behavior of prompt is slightly different from the Halo ComboBox. In ComboBox, if prompt is defined, then selectedIndex defaults to -1. Otherwise, selectedIndex defaults to 0. In the Spark DropDownList, the value of prompt does not affect the default value of selectedIndex. Instead, the developer can use the requiredSelection property to change the default value of selectedIndex. DropDownList inherits the dataGroup skin part from SkinnableDataContainer. This skin part is typically contained in a PopUpAnchor class or is adjacent to the anchor button. This skin part should only be visible when the skin is in the open state. It will be common to only include this skin part in the open state so that it has no memory footprint when the DropDownList is closed. The default skin contains the three skin parts, openButton, labelElement and dataGroup. Because the dropDown button looks different than a regular button, there is a separate skin for it called DropDownListButtonSkin. DropDownControllerThe DropDownController class handles the mouse, keyboard, and focus interactions for an anchor button and its dropDown. This helper class should be used by other dropDown components to handle the opening and closing of the dropDown due to user interactions. DropDownController contains an openButton property and a dropDown property, which typically are set to the corresponding skin parts in the host dropDown component. It has an isOpen property which is true when the dropDown is visible. The openDropDown and closeDropDown functions control whether the dropDown is open or not. The DropDownController will dispatch a DropDownEvent.OPEN event when the dropDown is opened and a DropDownEvent.CLOSE event when the dropDown is closed. Note that the DropDownController isn't responsible for putting the dropDown into the open or close state. Instead, the dropDown component listens for the DropDownEvent.OPEN and DropDownEvent.CLOSE events and takes the approriate action. DropDownList changes its skin state to normal or open in response to the DropDownController events. DropDownController has a processFocusOut function which is called by the host component when it loses focus. It also has a processKeyDown event which is called by the host component when it receives a keyDown event. DropDownController listens for different user interactions which either open or close the dropDown. The controller will open on a FlexEvent.BUTTON_DOWN event from the openButton. If rollOverOpenDelay is not NaN, then it will open on a MouseEvent.ROLL_OVER instead of the button down event. The controller will also open in response to the CTRL-DOWN key combination. Clicking anywhere outside of the dropDown will cause the DropDownController to close is rollOverOpenDelay is NaN. Otherwise, releasing the mouse button and moving the mouse anywhere outside of the openButton or dropDown will close the DropDownController. Pressing the CTRL-UP key combination or the ENTER key will close the dropDown. Pressing the ESC key will close the dropDown and cancel the selection. It is the responsibility of the dropDown component to cancel the selection if the DropDownEvent.CLOSE dispatched from the DropDownController has been cancelled. If the dropDown loses focus or the stage is resized, then the DropDownController will close. A typical dropDown component will incorporate a DropDownController instance by performing the following steps:
AnimationSince the skin has several skin states, the animations for opening and closing the dropDown can be defined in the skin as transitions between the normal and open states. Differences between Halo ComboBox and Spark DropDownList
API DescriptionDropDownList.as package spark.components { /** * Dispatched when the dropDown is dismissed for any reason such when * the user: * * selects an item in the dropDown * clicks outside of the dropDown * clicks the dropDown button while the dropDown is * displayed * * * @eventType mx.events.DropdownEvent.CLOSE */ [Event(name="close", type="mx.events.DropdownEvent")] /** * Dispatched when the user clicks the dropDown button * to display the dropDown. It is also dispatched if the user * uses the keyboard and types Ctrl-Down to open the dropDown. * * @eventType mx.events.DropdownEvent.OPEN */ [Event(name="open", type="mx.events.DropdownEvent")] /** * Normal State of the DropDown component */ [SkinState("normal")] /** * Open State of the DropDown component */ [SkinState("open")] /** * Disabled State of the DropDown component */ [SkinState("disabled")] /** * DropDownList control contains a drop-down list * from which the user can select a single value. * Its functionality is very similar to that of the * SELECT form element in HTML. * */ public class DropDownList extends List { /** * An optional skin part that holds the prompt or the text of the selectedItem */ [SkinPart(required="false")] public var labelElement:TextGraphicElement; /** * A skin part that defines the anchor button. */ [SkinPart(required="true")] public var openButton:ButtonBase; /** * Instance of the helper class that handles all of the mouse, keyboard * and focus user interactions. */ protected function get dropDownController():DropDownController; protected function set dropDownController(value:DropDownController); /** * The prompt for the DropDownList control. A prompt is * a String that is displayed in the TextInput portion of the * DropDownList when selectedIndex= -1. It is usually * a String like "Select one...". If there is no * prompt, the DropDownList control set selectedIndex to 0 * and displays the first item in the dataProvider. */ public function get prompt():String; public function set prompt(value:String):void; /** * Initializes the dropDown and changes the skin state to open. */ public function openDropDown():void; /** * Changes the skin state to normal, commits the data from the dropDown and * performs some cleanup. * * The user can close the dropDown either in a committing or non-committing manner * based on their interaction gesture. If the user has performed a committing * gesture, then set commitData to true. * * @param commitData Flag indicating if the component should commit the selected * data from the dropDown. If this flag is true, then commitDropDownData will be called. */ public function closeDropDown(commitData:Boolean):void; /** * Event handler for the <code>dropDownController</code> * <code>DropdownEvent.OPEN</code> event. Updates the skin's state and * ensures that the selectedItem is visible. */ protected function dropDownController_openHandler(event:DropdownEvent):void; /** * Event handler for the <code>dropDownController</code> * <code>DropdownEvent.CLOSE</code> event. Updates the skin's state. */ protected function dropDownController_closeHandler(event:DropdownEvent):void; } } DropDownController.as /** * DropDownController handles the mouse, keyboard, and focus * interactions for an anchor button and its dropDown. This helper class * should be used by other dropDown components to handle the opening * and closing of the dropDown due to user interactions. */ public class DropDownController extends EventDispatcher /** * Reference to the openButton skin part of the dropDown component. */ public function set openButton(value:ButtonBase):void public function get openButton():ButtonBase /** * Reference to the dropDown skin part of the dropDown component. */ public function set dropDown(value:DisplayObject):void public function get dropDown():DisplayObject /** * Whether the dropDown is open or not. */ public function get isOpen():Boolean /** * Specifies the delay, in milliseconds, to wait for opening the drop down * when the anchor button is rolled over. * If set to NaN, then the drop down opens on a click, not a rollover. */ public function get rollOverOpenDelay():Number public function set rollOverOpenDelay(value:Number):void /** * Opens the dropDown and dispatches a <code>DropdownEvent.OPEN</code> event. */ public function openDropDown():void /** * Closes the dropDown and dispatches a <code>DropdownEvent.CLOSE</code> event. * * @param commitData Flag indicating if the component should commit the selected * data from the dropDown. */ public function closeDropDown(commitData:Boolean):void /** * Called when the buttonDown event is dispatched. This function opens or closes * the dropDown depending upon the dropDown state. */ protected function openButton_buttonDownHandler(event:Event):void /** * Called when the openButton's rollOver event is dispatched. This function opens * the dropDown, or opens the drop down after the rollOverOpenDelay. */ protected function openButton_rollOverHandler(event:MouseEvent):void /** * Called when the systemManager receives a mouseDown event. This closes * the dropDown if the target is outside of the dropDown. */ protected function systemManager_mouseDownHandler(event:Event):void /** * Called when the dropdown is popped up from a rollover and the mouse moves * anywhere on the screen. If the mouse moves over the openButton or the dropdown, * the popup will stay open. Otherwise, the popup will close. */ protected function systemManager_mouseMoveHandler(event:Event):void /** * Close the dropDown if the stage has been resized. */ protected function systemManager_resizeHandler(event:Event):void /** * Closes the dropDown if focus it is no longer in focus. */ public function processFocusOut(event:FocusEvent):void /** * Handles the keyboard user interactions. * * @return Returns true if the <code>keyCode</code> was * recognized and handled. */ public function processKeyDown(event:KeyboardEvent):Boolean B FeaturesComboBox is a DropDownList that contains an editable textInput instead of a button. It supports inputting a value not contained in the dataProvider. Examples and UsageExample MXML Usage <DropDownList width="140" > <dataProvider> <ArrayCollection> <String>1. Alabama</String> <String>2. Alaska</String> <String>3. Arizona</String> <String>4. Arkansas</String> <String>5. California</String> </ArrayCollection> </dataProvider> </DropDownList> Example Skin Definition <SparkSkin xmlns="http://ns.adobe.com/mxml/2009"> <!-- host component --> <Metadata> [HostComponent("spark.components.DropDownList")] </Metadata> <states> <State name="normal"/> <State name="open"/> <State name="disabled"/> </states> <Popup includeIn="open" width="100%" height="100%" placement="below"> <Group maxHeight="100"> <!-- border --> <Rect left="0" right="0" top="0" bottom="0"> <stroke> <SolidColorStroke color="0x686868" weight="1"/> </stroke> </Rect> <!-- fill --> <Rect id="background" left="1" right="1" top="1" bottom="1" > <fill> <SolidColor id="bgFill" color="0xFFFFFF" /> </fill> </Rect> <Scroller left="1" top="1" right="1" bottom="1" id="scroller"> <DataGroup id="dataGroup" itemRenderer="spark.skins.default.DefaultItemRenderer"> <layout> <VerticalLayout gap="0" horizontalAlign="contentJustify" /> </layout> </DataGroup> </Scroller> <filters> <DropShadowFilter blurX="20" blurY="20" distance="5" angle="90" alpha="0.6" /> </filters> </Group> </Popup> <Button id="button" width="100%" height="100%" skinClass="spark.skins.default.DropDownListButtonSkin"/> <SimpleText id="labelElement" left="5" right="5" top="5" bottom="5" /> </SparkSkin>
Example Skin w/ Customized Data Rendering <SparkSkin xmlns="http://ns.adobe.com/mxml/2009"> <!-- host component --> <Metadata> [HostComponent("spark.components.DropDownList")] </Metadata> <states> <State name="normal"/> <State name="open"/> <State name="disabled"/> </states> <Popup includeIn="open" width="100%" height="100%" placement="below"> <Group maxHeight="100"> <!-- border --> <Rect left="0" right="0" top="0" bottom="0"> <stroke> <SolidColorStroke color="0x686868" weight="1"/> </stroke> </Rect> <!-- fill --> <Rect id="background" left="1" right="1" top="1" bottom="1" > <fill> <SolidColor id="bgFill" color="0xFFFFFF" /> </fill> </Rect> <Scroller left="1" top="1" right="1" bottom="1" id="scroller"> <DataGroup id="dataGroup" itemRenderer="spark.skins.default.DefaultItemRenderer"> <layout> <VerticalLayout gap="0" horizontalAlign="contentJustify" /> </layout> </DataGroup> </Scroller> <filters> <DropShadowFilter blurX="20" blurY="20" distance="5" angle="90" alpha="0.6" /> </filters> </Group> </Popup> <Button id="button" width="100%" height="100%" skinClass="spark.skins.default.DropDownListButtonSkin"/> <Group left="5" right="5" top="5" bottom="5" mouseEnabled="false" mouseChildren="false" > <layout> <HorizontalLayout gap="5"/> </layout> <Rect width="10" height="10"> <stroke> <SolidColorStroke weight="1" color="0x000000"/> </stroke> <fill> <SolidColor color="{hostComponent.selectedItem.color}"/> </fill> </Rect> <SimpleText width="100%" text="{hostComponent.selectedItem.label}"/> </Group> </SparkSkin> Additional Implementation DetailsPrototype WorkCompiler WorkNo compiler changes are required Web Tier Compiler ImpactNo impact on web tier compiler Flex Feature DependenciesThere is a dependency on the PopUpAnchor component feature. The default DropDownList skin requires it.
Backwards CompatibilitySyntax changesNone BehaviorNone Warnings/DeprecationNone AccessibilityThis component needs support for accessibility. PerformanceMake the dataGroup skin part optional so that it only is created when the DropDownList is opened. GlobalizationSince the classes are composites of other components, it relies on these components to support globalization. LocalizationCompiler FeaturesN/A Framework FeaturesNone Issues and RecommendationsOpen IssuesHow does DropDownList calculate is measured size? Should the measuredWidth be the same as the dropdown's width? Should the DropDownList iterate through the dataProvider, apply each item to the anchor data renderer and set measuredWidth to the largest width? Another option is to add a typicalItem property. The measured size would be the size of the DropDownList when displaying the typicalItem. Resolved IssuesShould we make dataGroup skin part an optional part? This would allow us to include the dataGroup skin part only in the open state, thus saving memory while the DropDownList is closed. The dataGroup skin part is now an optional skin part How should the DropDownList pass the selectedItem and the selectedItem's text representation (applying labelField/labelFunction to the data) to the skin? Currently it sets the labelElement skin part to the text representation and doesn't pass the selectedItem. Should we get rid of the labelElement skin part and pass the string to the anchor button's label? There are numerous ways to either push or pull this information. The DropDownList will set the labelElement.text property. We need to modify List and ListBase to support non-committing selection. For DropDownList, we only want the selectedIndex to change when the dropDown is closed. For example, when the user uses the arrow keys to choose a selection, this should not change the selectedIndex of the DropDownList until the dropDown is closed. Pressing the ESC button should reset the selectedIndex back to the value it had when the dropDown was opened. Do we need a helper class to handle opening and closing the dropDown? Or can this logic just get embedded in each dropDown component class? The DropDownController class is the helper class that handles user interaction What should happen with a DropDownList that has a prompt when it is selected? Can it then be unselected? Would this just show the prompt again? What user gestures would unselect the item? Setting the selectedIndex to -1 programmatically will show the prompt. The prompt is the text that is passed to the labelElement when there is no selection. It is possible to unselect a selection via keyboard gestures, but not via mouse gestures. DocumentationNone QANone |
|
| You must be logged in to comment. |
|---|

Comments (1)
Nov 27
Srividhya Bharathan says:
Hi, I just wanted to know as how can I get the selected Label of the dropdown. ...Hi,
I just wanted to know as how can I get the selected Label of the dropdown. I just needed to override the function.