////////////////////////////////////////////////////////////////////////////////
//
//  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.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.ui.Keyboard;
import flash.utils.Timer;

import mx.core.IDataRenderer;
import mx.core.IFactory;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.managers.IFocusManagerComponent;

import spark.effects.animation.Animation;
import spark.effects.animation.MotionPath;
import spark.effects.animation.SimpleMotionPath;
import spark.effects.easing.Sine;
import spark.events.TrackBaseEvent;
import spark.formatters.NumberFormatter;

use namespace mx_internal;

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

include "../../styles/metadata/BasicInheritingTextStyles.as"

/**
 *  The alpha of the focus ring for this component.
 *
 *  @default 0.55
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="focusAlpha", type="Number", inherit="no", theme="spark, mobile", minValue="0.0", maxValue="1.0")]

/**
 *  @copy spark.components.supportClasses.GroupBase#focusColor
 *
 *  @default 0xFFFFFF
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */ 
[Style(name="focusColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

/**
 *  When <code>true</code>, the thumb's value is
 *  committed as it is dragged along the track instead
 *  of when the thumb button is released.
 *  
 *  @default true
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="liveDragging", type="Boolean", inherit="no")]

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

[Exclude(name="color", kind="style")]
[Exclude(name="fontSize", kind="style")]
[Exclude(name="fontWeight", kind="style")]
[Exclude(name="textAlign", kind="style")]

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

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

/**
 *  The SliderBase class lets users select a value by moving a slider thumb between 
 *  the end points of the slider track. 
 *  The current value of the slider is determined by the relative location of 
 *  the thumb between the end points of the slider, 
 *  corresponding to the slider's minimum and maximum values.
 *
 *  The SliderBase class is a base class for HSlider and VSlider.
 *
 *  @mxml
 *
 *  <p>The <code>&lt;s:SliderBase&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:SliderBase
 *    <strong>Properties</strong>
 *    dataTipFormatFunction="20"
 *    dataTipPrecision="2"
 *    maximum="10"
 *    showDataTip="true"
 *    maxDragRate=30
 * 
 *    <strong>Styles</strong>
 *    alignmentBaseline="USE_DOMINANT_BASELINE"
 *    baselineShift="0.0"
 *    cffHinting="HORIZONTAL_STEM"
 *    color="0"
 *    digitCase="DEFAULT"
 *    digitWidth="DEFAULT"
 *    direction="LTR"
 *    dominantBaseline="AUTO"
 *    focusAlph="0.55"
 *    focusColor="0xFFFFFF"
 *    fontFamily="Arial"
 *    fontLookup="DEVICE"
 *    fontSize="12"
 *    fontStyle="NORMAL"
 *    fontWeight="NORMAL"
 *    justificationRule="AUTO"
 *    justificationStyle="AUTO"
 *    kerning="AUTO"
 *    ligatureLevel="COMMON"
 *    lineHeight="120%"
 *    lineThrough="false"
 *    liveDragging="true"
 *    local="en"
 *    renderingMode="CFF"
 *    textAlignLast="START"
 *    textAlpha="1"
 *    textDecoration="NONE"
 *    textJustify="INTER_WORD"
 *    trackingLeft="0"
 *    trackingRight="0"
 *    typographicCase="DEFAULT"
 *  /&gt;
 *  </pre> 
 *  
 *  @see spark.components.HSlider
 *  @see spark.components.VSlider
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class SliderBase extends TrackBase implements IFocusManagerComponent
{
    include "../../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class mixins
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Placeholder for mixin by SliderBaseAccImpl.
     */
    mx_internal static var createAccessibilityImplementation:Function;

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

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

        maximum = 10;
    }

    //--------------------------------------------------------------------------
    //
    //  Skin parts
    //
    //--------------------------------------------------------------------------

    [SkinPart(required="false", type="mx.core.IDataRenderer")]
    
    /**
     *  A skin part that defines a dataTip that displays a formatted version of 
     *  the current value. The dataTip appears while the thumb is being dragged.
     *  This is a dynamic skin part and must be of type IFactory.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var dataTip:IFactory; 

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

	/**
	 *  Maximum number of times per second we will change the slider position
	 *  and update the display while dragging.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion Flex 4
	 */
	protected var maxDragRate:Number = 30;

    /**
     *  @private
     */
    private var dataFormatter:NumberFormatter;

    /**
     *  @private
     */
    private var animator:Animation = null;
    
    /**
     *  @private
     */
    private var dataTipInitialPosition:Point;
    
    /**
     *  @private
     */
    private var dataTipInstance:IDataRenderer;

    /**
     *  @private
     */
    private var slideToValue:Number;
    
    /**
     *  @private
     */
    private var isKeyDown:Boolean = false;

    /**
     *  @private
     *  Location of the mouse down event on the thumb, relative to the thumb's origin.
     *  Used to update the value property when the mouse is dragged. 
     */
    private var clickOffset:Point;  
        
    /**
     *  @private
     *  Local coordinates of most recent mouse move.
     */
    private var mostRecentMousePoint:Point;
    
    /**
     *  @private
     *  Timer used to do drag scrolling.
     */
    private var dragTimer:Timer = null;
    
    /**
     *  @private
     *  True when there's a pending mouse move (stored in mostRecentMousePoint)
     *  that needs to be handled in the dragTimer handler. 
     */
    private var dragPending:Boolean = false;

    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------    

    //---------------------------------
    //  maximum
    //---------------------------------   

    [Inspectable(category="General", defaultValue="10.0")]
    
    /**
     *  Number which represents the maximum value possible for 
     *  <code>value</code>. If the values for either 
     *  <code>minimum</code> or <code>value</code> are greater
     *  than <code>maximum</code>, they will be changed to 
     *  reflect the new <code>maximum</code>
     *
     *  @default 10
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get maximum():Number
    {
        return super.maximum;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------    

    //--------------------------------- 
    //  dataTipformatFunction
    //---------------------------------

    /**
     *  @private
     */
    private var _dataTipFormatFunction:Function;
    
    /**
     *  Callback function that formats the data tip text.
     *  The function takes a single Number as an argument
     *  and returns a formatted String.
     *
     *  <p>The function has the following signature:</p>
     *  <pre>
     *  funcName(value:Number):Object
     *  </pre>
     *
     *  <p>The following example prefixes the data tip text with a dollar sign and 
     *  formats the text using the <code>dataTipPrecision</code> 
     *  of a SliderBase Control named 'slide': </p>
     *
     *  <pre>
     *  import mx.formatters.NumberBase;
     *  function myDataTipFormatter(value:Number):Object { 
     *      var dataFormatter:NumberBase = new NumberBase(".", ",", ".", ""); 
     *      return   "$ " + dataFormatter.formatPrecision(String(value), slide.dataTipPrecision); 
     *  }
     *  </pre>
     *
     *  @default undefined   
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get dataTipFormatFunction():Function
    {
        return _dataTipFormatFunction;
    }

    /**
     *  @private
     */
    public function set dataTipFormatFunction(value:Function):void
    {
        _dataTipFormatFunction = value;
    }
    
    //--------------------------------- 
    //  dataTipPrecision
    //---------------------------------

    [Inspectable(defaultValue="2", minValue="0")]
    
    /**
     *  Number of decimal places to use for the data tip text.
     *  A value of 0 means to round all values to an integer.
     *  This value is ignored if <code>dataTipFormatFunction</code> is defined.
     * 
     *  @default 2
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var dataTipPrecision:int = 2;
    
    //----------------------------------
    //  pendingValue
    //----------------------------------
    
    /**
     *  @private
     */
    private var _pendingValue:Number = 0;
    
    /**
     *  The value the slider will have when the mouse button is released. This property
     *  also holds the temporary values set during an animation of the thumb if
     *  the <code>liveDragging</code> style is true; the real value is only set
     *  when the animation ends.
     * 
     *  <p>If the <code>liveDragging</code> style is false, then the slider's value is only set
     *  when the mouse button is released. The value is not updated while the slider thumb is
     *  being dragged.</p>
     * 
     *  <p>This property is updated when the slider thumb moves, even if 
     *  <code>liveDragging</code> is false.</p>
     *  
     *  @default 0
     *  @return The value implied by the thumb position. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function get pendingValue():Number
    {
        return _pendingValue;
    }
    
    /**
     *  @private
     */
    protected function set pendingValue(value:Number):void
    {
        if (value == _pendingValue)
            return;
        _pendingValue = value;
        invalidateDisplayList();
    }
    
    //--------------------------------- 
    //  showDataTip
    //---------------------------------
    
    /**
     *  If set to <code>true</code>, shows a data tip during user interaction
     *  containing the current value of the slider. In addition, the skinPart,
     *  <code>dataTip</code>, must be defined in the skin in order to 
     *  display a data tip. 
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var showDataTip:Boolean = true;

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override protected function initializeAccessibility():void
    {
        if (SliderBase.createAccessibilityImplementation != null)
            SliderBase.createAccessibilityImplementation(this);
    }

    /**
     *  @private
     */  
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);
        
        // Prevent focus on our children so that focus remains with the SliderBase
        if (instance == thumb)
            thumb.focusEnabled = false;
        else if (instance == track)
            track.focusEnabled = false;
    }
    
    /**
     *  @private
     */
    override public function drawFocus(isFocused:Boolean):void
    {
        // if there's a thumb, just draw focus on the thumb; 
        // otherwise, draw it on the whole component
        if (thumb)
        {
            thumb.drawFocusAnyway = true;
            thumb.drawFocus(isFocused);
        }
        else
        {
            super.drawFocus(isFocused);
        }
    }
    
    /**
     *  @private
     *  Keep the pendingValue in sync with the actual value so that updateSkinDisplayList()
     *  overrides can just use pendingValue.
     */
    override protected function setValue(value:Number):void
    {
        _pendingValue = value;

        super.setValue(value);
    }

    /**
     *  @private
     */
    override mx_internal function updateErrorSkin():void
    {
        // Don't draw the error skin
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Used to position the data tip when it is visible. Subclasses must implement
     *  this function. 
     *  
     *  @param dataTipInstance The <code>dataTip</code> instance to update and position
     *  @param initialPosition The initial position of the <code>dataTip</code> in the skin
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function updateDataTip(dataTipInstance:IDataRenderer, initialPosition:Point):void
    {
        // Override in the subclasses
    }

    /**
     *  @private
     *  Returns a formatted version of the value
     */
    private function formatDataTipText(value:Number):Object
    {
        var formattedValue:Object;
            
        if (dataTipFormatFunction != null)
        {
            formattedValue = dataTipFormatFunction(value); 
        }
        else
        {
            if (dataFormatter == null)
            {
                dataFormatter = new NumberFormatter();
                addStyleClient(dataFormatter);
            }
                
            dataFormatter.fractionalDigits = dataTipPrecision;
            dataFormatter.trailingZeros = true;
            
            formattedValue = dataFormatter.format(value);   
        }
        
        return formattedValue;
    }
  
    /**
     *  @private
     *  Handles events from the Animation that runs the animated slide.
     *  We just call setValue() with the current animated value
     */
    private function animationUpdateHandler(animation:Animation):void
    {
        pendingValue = animation.currentValue["value"];
    }
    
    /**
     *  @private
     *  Handles end event from the Animation that runs the animated slide.
     *  We dispatch the "changeEnd" event at this time, after the animation
     *  is done since each animation occurs after a user interaction.
     */
    private function animationEndHandler(animation:Animation):void
    {
        setValue(slideToValue);
        
        dispatchEvent(new Event(Event.CHANGE));
        dispatchEvent(new FlexEvent(FlexEvent.CHANGE_END));
    }
    
    /**
     *  @private
     *  Stops a running animation prematurely and sets the value
     *  of the slider to the current pendingValue. We also dispatch
     *  a "changeEnd" event since the user has started another interaction.
     */
    private function stopAnimation():void
    {
        animator.stop();
        
        setValue(nearestValidValue(pendingValue, snapInterval));
        
        dispatchEvent(new Event(Event.CHANGE));
        dispatchEvent(new FlexEvent(FlexEvent.CHANGE_END));
    }
    
    //--------------------------------------------------------------------------
    // 
    //  Overridden event handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override protected function thumb_mouseDownHandler(event:MouseEvent):void
    {
        // finish previous animation
        if (animator && animator.isPlaying)
            stopAnimation();
        
        super.thumb_mouseDownHandler(event);
        clickOffset = thumb.globalToLocal(new Point(event.stageX, event.stageY));
                
        // Popup a dataTip only if we have a SkinPart and the boolean flag is true
        if (dataTip && showDataTip && enabled)
        {
            dataTipInstance = IDataRenderer(createDynamicPartInstance("dataTip"));
            
            dataTipInstance.data = formatDataTipText(
                nearestValidValue(pendingValue, snapInterval));
            
            var tipAsUIComponent:UIComponent = dataTipInstance as UIComponent;
            
            // Allow styles to be inherited from SliderBase.
            if (tipAsUIComponent)
            {
                tipAsUIComponent.owner = this;
                tipAsUIComponent.isPopUp = true;
            }

            systemManager.toolTipChildren.addChild(DisplayObject(dataTipInstance));
            
            // Force the dataTip to render so that we have the correct size since
            // updateDataTip might need the size
            if (tipAsUIComponent)
            {
                tipAsUIComponent.validateNow();
                tipAsUIComponent.setActualSize(tipAsUIComponent.getExplicitOrMeasuredWidth(),
                                               tipAsUIComponent.getExplicitOrMeasuredHeight());
            }
            
            dataTipInitialPosition = new Point(DisplayObject(dataTipInstance).x, 
                                                DisplayObject(dataTipInstance).y);   
            updateDataTip(dataTipInstance, dataTipInitialPosition);
        }
    }
    
    /**
     *  @private
     */
    private function handleMousePoint(p:Point):void
    {
        var newValue:Number = pointToValue(p.x - clickOffset.x, p.y - clickOffset.y);
        newValue = nearestValidValue(newValue, snapInterval);
        
        if (newValue != pendingValue)
        {
            dispatchEvent(new TrackBaseEvent(TrackBaseEvent.THUMB_DRAG));
            if (getStyle("liveDragging") === true)
            {
                setValue(newValue);
                dispatchEvent(new Event(Event.CHANGE));
            }
            else
            {
                pendingValue = newValue;
            }
        }
        
        if (dataTipInstance && showDataTip)
        {
            // If showing the dataTip, we need to validate to
            // make sure the thumb is in the right position.
            //validateNow();
            
            dataTipInstance.data = formatDataTipText(pendingValue);
            
            // Force the dataTip to render so that we have the correct size since
            // updateDataTip might need the size
            var tipAsUIComponent:UIComponent = dataTipInstance as UIComponent; 
            if (tipAsUIComponent)
            {
                tipAsUIComponent.validateNow();
                tipAsUIComponent.setActualSize(tipAsUIComponent.getExplicitOrMeasuredWidth(),tipAsUIComponent.getExplicitOrMeasuredHeight());
            }

            updateDataTip(dataTipInstance, dataTipInitialPosition);
        }
    }

    /**
     *  @private
     */
    override protected function system_mouseMoveHandler(event:MouseEvent):void
    {      
        if (!track)
            return;

        mostRecentMousePoint = track.globalToLocal(new Point(event.stageX, event.stageY));
        if (!dragTimer)
        {
            dragTimer = new Timer(1000/maxDragRate, 0);
            dragTimer.addEventListener(TimerEvent.TIMER, dragTimerHandler);
        }
        
        if (!dragTimer.running)
        {
            // This changes the slider value and invalidates the display list.
            handleMousePoint(mostRecentMousePoint);
            event.updateAfterEvent();

            // Start the periodic timer that will do subsequent drag 
            // scrolling if necessary. 
            dragTimer.start();
            
            // No additional mouse events received yet, so no scrolling pending.
            dragPending = false;
        }
        else
        {
            dragPending = true;
        }
    }
        
    /**
     *  @private
     *  Used to periodically change the slider value during a drag gesture.
     */
    private function dragTimerHandler(event:TimerEvent):void
    {
        if (dragPending)
        {
            // This changes the slider value and invalidates the display list.
            handleMousePoint(mostRecentMousePoint);

            // Call updateAfterEvent() to make sure it looks smooth
            event.updateAfterEvent();
            
            // No scroll is pending now. 
            dragPending = false;
        }
        else
        {
            // The timer elapsed with no mouse events, so we'll
            // just turn the timer off for now.  It will get turned
            // back on if another mouse event comes in.
            dragTimer.stop();
        }
    }
        
    /**
     *  @private
     */
    override protected function system_mouseUpHandler(event:Event):void
    {
        if (dragTimer)
        {
            if (dragPending)
            {
                // This changes the slider value and invalidates the display list.
                handleMousePoint(mostRecentMousePoint);
                
                // Call updateAfterEvent() to make sure it looks smooth
                if (event is MouseEvent)
                    MouseEvent(event).updateAfterEvent();
            }
            // The drag gesture is over, so we no longer need the timer.
            dragTimer.stop();
            dragTimer.removeEventListener(TimerEvent.TIMER, dragTimerHandler);
            dragTimer = null;
        }
        
        if ((getStyle("liveDragging") === false) && (value != pendingValue))
        {
            setValue(pendingValue);
            dispatchEvent(new Event(Event.CHANGE));
        }

        if (dataTipInstance)
        {
            removeDynamicPartInstance("dataTip", dataTipInstance);
            systemManager.toolTipChildren.removeChild(DisplayObject(dataTipInstance));
            dataTipInstance = null;
        }
        
        super.system_mouseUpHandler(event);
    }
    
    /**
     *  @private
     *  Handle keyboard events. Left/Down decreases the value
     *  decreases the value by stepSize. The opposite for
     *  Right/Up arrows. The Home and End keys set the value
     *  to the min and max respectively.
     *  
     *  We dispatch changing events when the keystroke 
     *  may both repeat and alter the value.
     */
    override protected function keyDownHandler(event:KeyboardEvent):void
    {
        super.keyDownHandler(event);
       
        if (event.isDefaultPrevented())
            return;

        if (animator && animator.isPlaying)
            stopAnimation();
        
        var prevValue:Number = this.value;
        var newValue:Number;

        // If rtl layout, need to swap LEFT/UP and RIGHT/DOWN so correct action
        // is done.
        var keyCode:uint = mapKeycodeForLayoutDirection(event, true);
                                
        switch (keyCode)
        {
            case Keyboard.DOWN:
            case Keyboard.LEFT:
            {
                newValue = nearestValidValue(pendingValue - stepSize, snapInterval);
                
                if (prevValue != newValue)
                {
                    if (!isKeyDown)
                    {
                        dispatchEvent(new FlexEvent(FlexEvent.CHANGE_START));
                        isKeyDown = true;
                    }
                    setValue(newValue);
                    dispatchEvent(new Event(Event.CHANGE));
                }
                event.preventDefault();
                break;
            }

            case Keyboard.UP:
            case Keyboard.RIGHT:
            {
                newValue = nearestValidValue(pendingValue + stepSize, snapInterval);
                
                if (prevValue != newValue)
                {
                    if (!isKeyDown)
                    {
                        dispatchEvent(new FlexEvent(FlexEvent.CHANGE_START));
                        isKeyDown = true;
                    }
                    setValue(newValue);
                    dispatchEvent(new Event(Event.CHANGE));
                }
                event.preventDefault();
                break;
            }
            
            case Keyboard.HOME:
            {
                value = minimum;
                if (value != prevValue)
                    dispatchEvent(new Event(Event.CHANGE));
                event.preventDefault();
                break;
            }

            case Keyboard.END:
            {
                value = maximum;
                if (value != prevValue)
                    dispatchEvent(new Event(Event.CHANGE));
                event.preventDefault();
                break;
            }
        }
    }
    
    /**
     *  @private
     *  Handle keyboard release events. Allows us to send out changeEnd
     *  event.
     */
    override protected function keyUpHandler(event:KeyboardEvent) : void
    {
        switch (event.keyCode)
        {
            case Keyboard.DOWN:
            case Keyboard.LEFT:
            case Keyboard.UP:
            case Keyboard.RIGHT:
            {
                if (isKeyDown)
                {
                    // Dispatch "change" event only after a repeat occurs.
                    dispatchEvent(new FlexEvent(FlexEvent.CHANGE_END));
                    isKeyDown = false;
                }
                event.preventDefault();
                break;
            }
        }
    }
        
    /**
     *  @private
     *  Handle mouse-down events for the slider track. We
     *  calculate the value based on the new position and then
     *  move the thumb to the correct location as well as
     *  commit the value.
     */
    override protected function track_mouseDownHandler(event:MouseEvent):void
    {
        if (!enabled)
            return;
         
        // Offset the track-relative coordinates of this event so that
        // the thumb will end up centered over the mouse down location.
        var thumbW:Number = (thumb) ? thumb.width : 0;
        var thumbH:Number = (thumb) ? thumb.height : 0;
        var offsetX:Number = event.stageX - (thumbW / 2);
        var offsetY:Number = event.stageY - (thumbH / 2);
        var p:Point = track.globalToLocal(new Point(offsetX, offsetY));

        var newValue:Number = pointToValue(p.x, p.y);
        newValue = nearestValidValue(newValue, snapInterval);

        if (newValue != pendingValue)
        {
            var slideDuration:Number = getStyle("slideDuration");
            if (slideDuration != 0)
            {
                if (!animator)
                {
                    animator = new Animation();
                    var animTarget:AnimationTarget = new AnimationTarget(animationUpdateHandler);
                    animTarget.endFunction = animationEndHandler;
                    animator.animationTarget = animTarget;                    
                    // TODO (chaase): hard-coding easer for now - how to style it?
                    animator.easer = new Sine(0);
                }
                
                // Finish any current animation before we start the next one.
                if (animator.isPlaying)
                    stopAnimation();
                
                // holds the final value to be set when animation ends
                slideToValue = newValue;
                animator.duration = slideDuration * 
                    (Math.abs(pendingValue - slideToValue) / (maximum - minimum));
                animator.motionPaths = new <MotionPath>[
                    new SimpleMotionPath("value", pendingValue, slideToValue)];
                
                dispatchEvent(new FlexEvent(FlexEvent.CHANGE_START));
                animator.play();
            }
            else
            {
                setValue(newValue);
                dispatchEvent(new Event(Event.CHANGE));
            }
        }

        event.updateAfterEvent();
    }
}

}
