////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////


package spark.components.supportClasses
{

import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;

import mx.collections.IList;
import mx.core.InteractionMode;
import mx.events.CollectionEvent;
import mx.events.FlexEvent;

import spark.components.List;
import spark.core.NavigationUnit;
import spark.events.DropDownEvent;
import spark.events.IndexChangeEvent;

import mx.core.mx_internal;
use namespace mx_internal;

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  The radius of the corners for this component.
 *
 *  @default 4
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="spark")]

/**
 *  Controls the visibility of the drop shadow for this component.
 *
 *  @default true
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="dropShadowVisible", type="Boolean", inherit="no", theme="spark")]

//--------------------------------------
//  Events
//--------------------------------------

/**
 *  Dispatched when the drop-down list closes for any reason, such when 
 *  the user:
 *  <ul>
 *      <li>Selects an item in the drop-down list.</li>
 *      <li>Clicks outside of the drop-down list.</li>
 *      <li>Clicks the anchor button while the drop-down list is 
 *  displayed.</li>
 *  </ul>
 *
 *  @eventType spark.events.DropDownEvent.CLOSE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="close", type="spark.events.DropDownEvent")]

/**
 *  Dispatched when the user clicks the anchor button
 *  to display the drop-down list.  
 *  It is also dispatched if the user
 *  uses Control-Down to open the dropDown.
 *
 *  @eventType spark.events.DropDownEvent.OPEN
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="open", type="spark.events.DropDownEvent")]

//--------------------------------------
//  SkinStates
//--------------------------------------

/**
 *  Skin state for the open state of the DropDownListBase control.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[SkinState("open")]

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="allowMultipleSelection", kind="property")]
[Exclude(name="dragEnabled", kind="property")]
[Exclude(name="dragMoveEnabled", kind="property")]
[Exclude(name="dropEnabled", kind="property")]
[Exclude(name="selectedIndices", kind="property")]
[Exclude(name="selectedItems", kind="property")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[AccessibilityClass(implementation="spark.accessibility.DropDownListBaseAccImpl")]

/**
 *  The DropDownListBase 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.
 *
 *  <p>The DropDownListBase control consists of the anchor button, 
 *  and drop-down-list. 
 *  Use the anchor button to open and close the drop-down-list. 
 *  </p>
 *
 *  <p>When the drop-down list is open:</p>
 *  <ul>
 *    <li>Clicking the anchor button closes the drop-down list 
 *      and commits the currently selected data item.</li>
 *    <li>Clicking outside of the drop-down list closes the drop-down list 
 *      and commits the currently selected data item.</li>
 *    <li>Clicking on a data item selects that item and closes the drop-down list.</li>
 *    <li>If the <code>requireSelection</code> property is <code>false</code>, 
 *      clicking on a data item while pressing the Control key deselects 
 *      the item and closes the drop-down list.</li>
 *  </ul>
 *
 *  @mxml <p>The <code>&lt;s:DropDownListBase&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following attributes:</p>
 *
 *  <pre>
 *  &lt;s:DropDownListBase 
 *    <strong>Styles</strong>
 *    cornerRadius="4"
 *    dropShadowVisible="true"
 * 
 *    <strong>Events</strong>
 *    closed="<i>No default</i>"
 *    open="<i>No default</i>"
 *  /&gt;
 *  </pre>
 *
 *  @see spark.skins.spark.DropDownListSkin
 *  @see spark.components.supportClasses.DropDownController
 *
 *  @includeExample examples/DropDownListExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class DropDownListBase extends List
{
    include "../../core/Version.as";
 
    //--------------------------------------------------------------------------
    //
    //  Class mixins
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Placeholder for mixin by DropDownListBaseAccImpl.
     */
    mx_internal static var createAccessibilityImplementation:Function;
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function DropDownListBase()
    {
        super();

        dropDownController = new DropDownController();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Skin parts
    //
    //--------------------------------------------------------------------------    

    //----------------------------------
    //  dropDown
    //----------------------------------

    [SkinPart(required="false")]

    /**
     *  A skin part that defines the drop-down list area. When the DropDownListBase is open,
     *  clicking anywhere outside of the dropDown skin part closes the   
     *  drop-down list. 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var dropDown:DisplayObject;
    
    //----------------------------------
    //  openButton
    //----------------------------------

    [SkinPart(required="true")]

    /**
     *  A skin part that defines the anchor button.  
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var openButton:ButtonBase;
       
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    private var labelChanged:Boolean = false;
    // Stores the user selected index until the dropDown closes
    
    /**
     *  @private
     */
    mx_internal static var PAGE_SIZE:int = 5;
    
    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  allowMultipleSelection
    //----------------------------------
    
    /**
     *  @private
     */
    override public function set allowMultipleSelection(value:Boolean):void
    {
        // Don't allow this value to be set. If the multiple
        // selection related properties are set and 
        // allowMultipleSelection is false, List will
        // select the first item passed in. 
        return;
    }
       
    //----------------------------------
    //  dataProvider
    //----------------------------------
    
    [Inspectable(category="Data")]
    
    /**
     *  @private
     *  Update the label if the dataProvider has changed
     */
    override public function set dataProvider(value:IList):void
    {   
        if (dataProvider === value)
            return;
            
        super.dataProvider = value;
        labelChanged = true;
        invalidateProperties();
    }
    
    //----------------------------------
    //  dragEnabled
    //----------------------------------

    /**
     *  @private
     *  Excluded property
     */
    override public function set dragEnabled(value:Boolean):void
    {
    }

    //----------------------------------
    //  dragMoveEnabled
    //----------------------------------

    /**
     *  @private
     *  Excluded property
     */
    override public function set dragMoveEnabled(value:Boolean):void
    {
    }
    
    //----------------------------------
    //  dropEnabled
    //----------------------------------

    /**
     *  @private
     *  Excluded property
     */
    override public function set dropEnabled(value:Boolean):void
    {
    }
    
    //----------------------------------
    //  labelField
    //----------------------------------
    
    [Inspectable(category="Data", defaultValue="label")]
    
    /**
     *  @private
     */
    override public function set labelField(value:String):void
    {
        if (labelField == value)
            return;
            
        super.labelField = value;
        labelChanged = true;
        invalidateProperties();
    }
    
    //----------------------------------
    //  labelFunction
    //----------------------------------
    
    [Inspectable(category="Data")]
    
    /**
     *  @private
     */
    override public function set labelFunction(value:Function):void
    {
        if (labelFunction == value)
            return;
            
        super.labelFunction = value;
        labelChanged = true;
        invalidateProperties();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  dropDownController
    //----------------------------------
    
    /**
     *  @private
     */
    private var _dropDownController:DropDownController; 
    
    /**
     *  Instance of the DropDownController class that handles all of the mouse, keyboard 
     *  and focus user interactions. 
     * 
     *  Flex calls the <code>initializeDropDownController()</code> method after 
     *  the DropDownController instance is created in the constructor.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function get dropDownController():DropDownController
    {
        return _dropDownController;
    }
    
    /**
     *  @private
     */
    protected function set dropDownController(value:DropDownController):void
    {
        if (_dropDownController == value)
            return;
            
        _dropDownController = value;
		
        _dropDownController.addEventListener(DropDownEvent.OPEN, dropDownController_openHandler);
        _dropDownController.addEventListener(DropDownEvent.CLOSE, dropDownController_closeHandler);
            
		_dropDownController.closeOnResize = _closeDropDownOnResize;

		if (openButton)
            _dropDownController.openButton = openButton;
        if (dropDown)
            _dropDownController.dropDown = dropDown;    
    }
    
    //----------------------------------
    //  isDropDownOpen
    //----------------------------------
    
    /**
     *  @copy spark.components.supportClasses.DropDownController#isOpen
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get isDropDownOpen():Boolean
    {
        if (dropDownController)
            return dropDownController.isOpen;
        else
            return false;
    }
        
	//----------------------------------
	//  closeDropDownOnResize
	//----------------------------------

    /**
     *  @private
     *
     *  cached value: getStyle("interactionMode") == InteractionMode.TOUCH
     */
    private var isTouchInteractionMode:Boolean = false;

    /**
     *  @private
     *
     *  do not know what default value for closeDropDownOnResize will be until styles have been applied,
     *  but user may set property before that. this flag indicates whether property has been explicitly set,
     *  and so will not need to be determined from css when stylesInitialized() or styleChanged() is called.
     */
    private var isCloseDropDownOnResizeExplicitlySet:Boolean = false;

    /**
     *  @private
     */
    protected var _closeDropDownOnResize:Boolean = true;
	
    [Inspectable(category="General", enumeration="true,false", defaultValue="true")]
	
    /**
     *  When <code>true</code>, resizing the system manager
     *  closes the drop down.
     *  For mobile applications, this property is set
 	 *  to <code>false</code> so that the drop down stays open when the
     *  page orientation changes.
     *
 	 *  @default true
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.12
     */
    public function get closeDropDownOnResize():Boolean
	{
        return _closeDropDownOnResize;
    }

    /**
     *  @private
     */
    public function set closeDropDownOnResize(value:Boolean):void
	{
        setCloseDropDownOnResize(value, true);
    }
		
    /**
     *  @private
     */
    private function setCloseDropDownOnResize(value:Boolean, explicitlySet:Boolean):void
	{
        _closeDropDownOnResize = value;
        isCloseDropDownOnResizeExplicitlySet ||= explicitlySet;
        if (dropDownController)
            dropDownController.closeOnResize = _closeDropDownOnResize;
	}        

	//----------------------------------
    //  userProposedSelectedIndex
    //----------------------------------

    /**
     *  @private
     */
    private var _userProposedSelectedIndex:Number = NO_SELECTION;
    
    /**
     *  @private
     */
    mx_internal function set userProposedSelectedIndex(value:Number):void
    {
        _userProposedSelectedIndex = value;
    }
    
    /**
     *  @private
     */
    mx_internal function get userProposedSelectedIndex():Number
    {
        return _userProposedSelectedIndex;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    
	/**
	 *  @private
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.12
     */
    override public function stylesInitialized():void
    {
        super.stylesInitialized();
        setInteractionMode();
    }
	
    /**
     *  @private
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.12
     */
	override public function styleChanged(styleProp:String):void
	{
        super.styleChanged(styleProp);
        if (!styleProp || styleProp == "styleName" || styleProp == "interactionMode")
            setInteractionMode();
    }
		
    /**
     *  @private
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.12
     */
    private function setInteractionMode():void
    {
	    isTouchInteractionMode = getStyle("interactionMode") == InteractionMode.TOUCH;
        if (!isCloseDropDownOnResizeExplicitlySet)
            setCloseDropDownOnResize(!isTouchInteractionMode, false);
    }
		
    /**
     *  @private
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.12
     */
    override public function setSelectedIndex(rowIndex:int, dispatchChangeEvent:Boolean = false, changeCaret:Boolean = true):void
    {
	    super.setSelectedIndex(rowIndex, dispatchChangeEvent, changeCaret);
	    if (isTouchInteractionMode)
	    {
            userProposedSelectedIndex = rowIndex;
            closeDropDown(true);
        }
    }
		
		
    /**
     *  @private
     *  Called by the initialize() method of UIComponent
     *  to hook in the accessibility code.
     */ 
    override protected function initializeAccessibility():void
    {
        if (DropDownListBase.createAccessibilityImplementation != null)
            DropDownListBase.createAccessibilityImplementation(this);
    }
    /**
     *  @private
     */ 
    override protected function commitProperties():void
    {
        super.commitProperties();
        
        if (labelChanged)
        {
            labelChanged = false;
            updateLabelDisplay();
        }
    }
    
    /**
     *  @private
     */ 
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);
 
        if (instance == openButton)
        {
            if (dropDownController)
                dropDownController.openButton = openButton;
        }
        else if (instance == dropDown && dropDownController)
		{
            dropDownController.dropDown = dropDown;
		}
    }
    
    /**
     *  @private
     */
    override protected function partRemoved(partName:String, instance:Object):void
    {
        if (dropDownController)
        {
            if (instance == openButton)
                dropDownController.openButton = null;
        
            if (instance == dropDown)
                dropDownController.dropDown = null;
        }

        super.partRemoved(partName, instance);
    }
    
    /**
     *  @private
     */ 
    override protected function getCurrentSkinState():String
    {
        return !enabled ? "disabled" : isDropDownOpen ? "open" : "normal";
    }   
       
    /**
     *  @private
     */ 
    override protected function commitSelection(dispatchChangedEvents:Boolean = true):Boolean
    {
        var retVal:Boolean = super.commitSelection(dispatchChangedEvents);
        updateLabelDisplay();
        return retVal; 
    }
    
    /**
     *  @private
     *  In updateRenderer, we want to select the proposedSelectedIndex
     */
    override mx_internal function isItemIndexSelected(index:int):Boolean
    {
        return userProposedSelectedIndex == index;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------   

    /**
     *  Open the drop-down list and dispatch 
     *  a <code>DropdownEvent.OPEN</code> event.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */ 
    public function openDropDown():void
    {
        dropDownController.openDropDown();
    }
    
    /**
     *  Close the drop-down list and dispatch a <code>DropDownEvent.CLOSE</code> event. 
     *   
     *  @param commit If <code>true</code>, commit the selected
     *  data item. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function closeDropDown(commit:Boolean):void
    {
        dropDownController.closeDropDown(commit);
    }
    
    /**
     *  @private
     *  Called whenever we need to update the text passed to the labelDisplay skin part
     */
    // TODO (jszeto): Make this protected and make the name more generic (passing data to skin) 
    mx_internal function updateLabelDisplay(displayItem:* = undefined):void
    {
        // DropDownList and ComboBox will override this function
    }
    
    /**
     *  @private
     *  Called whenever we need to change the highlighted selection while the dropDown is open
     *  ComboBox overrides this behavior
     */
    mx_internal function changeHighlightedSelection(newIndex:int, scrollToTop:Boolean = false):void
    {
        // Store the selection in userProposedSelectedIndex because we 
        // don't want to update selectedIndex until the dropdown closes
        itemSelected(userProposedSelectedIndex, false);
        userProposedSelectedIndex = newIndex;
        itemSelected(userProposedSelectedIndex, true);
        
        positionIndexInView(userProposedSelectedIndex, scrollToTop ? 0 : NaN);
        
        var e:IndexChangeEvent = new IndexChangeEvent(IndexChangeEvent.CARET_CHANGE); 
        e.oldIndex = caretIndex;
        setCurrentCaretIndex(userProposedSelectedIndex);
        e.newIndex = caretIndex;
        dispatchEvent(e);
    }
    
    /**
     *  @private 
     */ 
    mx_internal function positionIndexInView(index:int, topOffset:Number = NaN, 
                                             bottomOffset:Number = NaN, 
                                             leftOffset:Number = NaN,
                                             rightOffset:Number = NaN):void
    {
        if (!layout || dataGroup == null)
            return;
        
        var spDelta:Point = 
            dataGroup.layout.getScrollPositionDeltaToElementHelper(index, topOffset, bottomOffset,
                                                                   leftOffset, rightOffset);
        
        if (spDelta)
        {
            dataGroup.horizontalScrollPosition += spDelta.x;
            dataGroup.verticalScrollPosition += spDelta.y;
        }
    }
          
    /**
     *  @private
     */ 
    override mx_internal function findKey(eventCode:int):Boolean
    {
        if (!dataProvider || dataProvider.length == 0)
            return false;
        
        if (eventCode >= 33 && eventCode <= 126)
        {
            var matchingIndex:Number;
            var keyString:String = String.fromCharCode(eventCode);
            var startIndex:int = isDropDownOpen ? userProposedSelectedIndex  + 1 : selectedIndex + 1;
            startIndex = Math.max(0, startIndex);
            
            matchingIndex = findStringLoop(keyString, startIndex, dataProvider.length); 
            
            // We didn't find the item, loop back to the top 
            if (matchingIndex == -1)
            {
                matchingIndex = findStringLoop(keyString, 0,  startIndex); 
            }
            
            
            if (matchingIndex != -1)
            {
                if (isDropDownOpen)
                    changeHighlightedSelection(matchingIndex);
                else
                    setSelectedIndex(matchingIndex, true); 
                
                return true;
            }
        }
        
        return false;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------   

    /**
     *  @private
     */ 
    override protected function dataProvider_collectionChangeHandler(event:Event):void
    {       
        super.dataProvider_collectionChangeHandler(event);
        
        if (event is CollectionEvent)
        {
            labelChanged = true;
            invalidateProperties();         
        }
    }
       
    /**
     *  @private
     */
    override protected function item_mouseDownHandler(event:MouseEvent):void
    {
        super.item_mouseDownHandler(event);
        if (!isTouchInteractionMode)
	    {
            userProposedSelectedIndex = selectedIndex;
            closeDropDown(true);
        }
    }
            
    /**
     *  @private
     */
    override protected function keyDownHandler(event:KeyboardEvent) : void
    {
        if (!enabled)
            return; 
                
        if (!dropDownController.processKeyDown(event))
        {
            // If rtl layout, need to swap Keyboard.LEFT and Keyboard.RIGHT.
            var navigationUnit:uint = mapKeycodeForLayoutDirection(event);
                                    
            if (findKey(event.charCode))
            {
                event.preventDefault();
                return;
            }
            
            if (!NavigationUnit.isNavigationUnit(navigationUnit))
                return;
            
            var proposedNewIndex:int = NO_SELECTION;
            var currentIndex:int;
                        
            if (isDropDownOpen)
            {   
                // Normalize the proposed index for getNavigationDestinationIndex
                currentIndex = userProposedSelectedIndex < NO_SELECTION ? NO_SELECTION : userProposedSelectedIndex;
                proposedNewIndex = layout.getNavigationDestinationIndex(currentIndex, navigationUnit, arrowKeysWrapFocus);
                
                if (proposedNewIndex != NO_SELECTION)
                {
                    changeHighlightedSelection(proposedNewIndex);
                    event.preventDefault();
                }
            }
            else if (dataProvider)
            {
                var maxIndex:int = dataProvider.length - 1;
                
                // Normalize the proposed index for getNavigationDestinationIndex
                currentIndex = caretIndex < NO_SELECTION ? NO_SELECTION : caretIndex;
                
                switch (navigationUnit)
                {
                    case NavigationUnit.UP:
                    {
                        if (arrowKeysWrapFocus && 
                            (currentIndex == 0 || 
                             currentIndex == NO_SELECTION || 
                             currentIndex == CUSTOM_SELECTED_ITEM))
                            proposedNewIndex = maxIndex;
                        else
                            proposedNewIndex = currentIndex - 1;  
                        event.preventDefault();
                        break;
                    }                      
        
                    case NavigationUnit.DOWN:
                    {
                        if (arrowKeysWrapFocus && 
                            (currentIndex == maxIndex || 
                             currentIndex == NO_SELECTION || 
                             currentIndex == CUSTOM_SELECTED_ITEM))
                            proposedNewIndex = 0;
                        else
                            proposedNewIndex = currentIndex + 1;  
                        event.preventDefault();
                        break;
                    }
                        
                    case NavigationUnit.PAGE_UP:
                    {
                        proposedNewIndex = currentIndex == NO_SELECTION ? 
                            NO_SELECTION : Math.max(currentIndex - PAGE_SIZE, 0);
                        event.preventDefault();
                        break;
                    }
                        
                    case NavigationUnit.PAGE_DOWN:
                    {    
                        proposedNewIndex = currentIndex == NO_SELECTION ?
                                           PAGE_SIZE : (currentIndex + PAGE_SIZE);
                        event.preventDefault();
                        break;
                    }
                       
                    case NavigationUnit.HOME:
                    {
                        proposedNewIndex = 0;
                        event.preventDefault();
                        break;
                    }

                    case NavigationUnit.END:
                    {
                        proposedNewIndex = maxIndex;  
                        event.preventDefault();
                        break;
                    }  
                       
                }
                
                proposedNewIndex = Math.min(proposedNewIndex, maxIndex);
                
                if (proposedNewIndex >= 0)
                {
                    userProposedSelectedIndex = proposedNewIndex;
                    setSelectedIndex(proposedNewIndex, true);
                }
            }
        }
        else
        {
            event.preventDefault();
        }
        
    }
    
    /**
     *  @private
     */
    override protected function focusOutHandler(event:FocusEvent):void
    {
        if (isOurFocus(DisplayObject(event.target)))
            dropDownController.processFocusOut(event);

        super.focusOutHandler(event);
    }
        
    /**
     *  @private
     *  Event handler for the <code>dropDownController</code> 
     *  <code>DropDownEvent.OPEN</code> event. Updates the skin's state and 
     *  ensures that the selectedItem is visible. 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function dropDownController_openHandler(event:DropDownEvent):void
    {
        addEventListener(FlexEvent.UPDATE_COMPLETE, open_updateCompleteHandler);
        userProposedSelectedIndex = selectedIndex;
        invalidateSkinState();  
    }
    
    /**
     *  @private
     */
    mx_internal function open_updateCompleteHandler(event:FlexEvent):void
    {   
        removeEventListener(FlexEvent.UPDATE_COMPLETE, open_updateCompleteHandler);
        positionIndexInView(selectedIndex, 0);
        
        dispatchEvent(new DropDownEvent(DropDownEvent.OPEN));
    }
    
    /**
     *  @private
     *  Event handler for the <code>dropDownController</code> 
     *  <code>DropDownEvent.CLOSE</code> event. Updates the skin's state.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function dropDownController_closeHandler(event:DropDownEvent):void
    {
        addEventListener(FlexEvent.UPDATE_COMPLETE, close_updateCompleteHandler);
        invalidateSkinState();
        
        if (!event.isDefaultPrevented())
        {
            // Even if the dropDown was programmatically closed, assume the selection 
            // changed as a result of a previous user interaction
            setSelectedIndex(userProposedSelectedIndex, true);  
        }
        else
        {
            changeHighlightedSelection(selectedIndex);
        }
    }

    /**
     *  @private
     */
    private function close_updateCompleteHandler(event:FlexEvent):void
    {   
        removeEventListener(FlexEvent.UPDATE_COMPLETE, close_updateCompleteHandler);
        
        dispatchEvent(new DropDownEvent(DropDownEvent.CLOSE));
    }
}

}
