| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 mx.controls.sliderClasses |
| { |
| |
| import flash.display.DisplayObject; |
| import flash.display.Graphics; |
| import flash.events.FocusEvent; |
| import flash.events.KeyboardEvent; |
| import flash.events.MouseEvent; |
| import flash.geom.Point; |
| |
| import mx.core.IFlexDisplayObject; |
| import mx.core.IUIComponent; |
| import mx.core.LayoutDirection; |
| import mx.core.UIComponent; |
| import mx.core.mx_internal; |
| import mx.effects.Tween; |
| import mx.events.FlexEvent; |
| import mx.events.SliderEvent; |
| import mx.events.SliderEventClickTarget; |
| import mx.formatters.NumberFormatter; |
| import mx.styles.ISimpleStyleClient; |
| import mx.styles.StyleProxy; |
| |
| use namespace mx_internal; |
| |
| //-------------------------------------- |
| // Events |
| //-------------------------------------- |
| |
| /** |
| * Dispatched when the slider changes value due to mouse or keyboard interaction. |
| * |
| * <p>If the <code>liveDragging</code> property is <code>true</code>, |
| * the event is dispatched continuously as the user moves the thumb. |
| * If <code>liveDragging</code> is <code>false</code>, |
| * the event is dispatched when the user releases the slider thumb.</p> |
| * |
| * @eventType mx.events.SliderEvent.CHANGE |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="change", type="mx.events.SliderEvent")] |
| |
| /** |
| * Dispatched when the slider's thumb is pressed and then moved by the mouse. |
| * This event is always preceded by a <code>thumbPress</code> event. |
| * @eventType mx.events.SliderEvent.THUMB_DRAG |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="thumbDrag", type="mx.events.SliderEvent")] |
| |
| /** |
| * Dispatched when the slider's thumb is pressed, meaning |
| * the user presses the mouse button over the thumb. |
| * |
| * @eventType mx.events.SliderEvent.THUMB_PRESS |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="thumbPress", type="mx.events.SliderEvent")] |
| |
| /** |
| * Dispatched when the slider's thumb is released, |
| * meaning the user releases the mouse button after |
| * a <code>thumbPress</code> event. |
| * |
| * @eventType mx.events.SliderEvent.THUMB_RELEASE |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="thumbRelease", type="mx.events.SliderEvent")] |
| |
| //-------------------------------------- |
| // Styles |
| //-------------------------------------- |
| |
| include "../../styles/metadata/FillStyles.as"; |
| |
| /** |
| * The color of the black section of the border. |
| * |
| * @default 0x919999 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="borderColor", type="uint", format="Color", inherit="no", theme="halo")] |
| |
| /** |
| * Color of the track highlight. |
| * |
| * @default #0099FF |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| [Style(name="accentColor", type="uint", format="Color", inherit="yes", theme="spark")] |
| |
| /** |
| * Color of focus ring when the component is in focus |
| * |
| * @default 0x70B2EE |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| [Style(name="focusColor", type="uint", format="Color", inherit="yes", theme="spark")] |
| |
| /** |
| * Invert the direction of the thumbs. |
| * If <code>true</code>, the thumbs will be flipped. |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="invertThumbDirection", type="Boolean", inherit="no")] |
| |
| /** |
| * The y-position offset (if direction is horizontal) |
| * or x-position offset (if direction is vertical) |
| * of the labels relative to the track. |
| * |
| * @default -10 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="labelOffset", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The name of the style to use for the slider label. |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="labelStyleName", type="String", inherit="no")] |
| |
| /** |
| * Duration in milliseconds for the sliding animation |
| * when you click on the track to move a thumb. |
| * |
| * @default 300 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="slideDuration", type="Number", format="Time", inherit="no")] |
| |
| /** |
| * Tweening function used by the sliding animation |
| * when you click on the track to move a thumb. |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="slideEasingFunction", type="Function", inherit="no")] |
| |
| /** |
| * The y-position offset (if direction is horizontal) |
| * or x-position offset (if direction is vertical) |
| * of the thumb relative to the track. |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="thumbOffset", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The color of the tick marks. |
| * Can be a hex color value or the string name of a known color. |
| * |
| * @default 0x6F7777. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tickColor", type="uint", format="Color", inherit="no")] |
| |
| /** |
| * The length in pixels of the tick marks. |
| * If <code>direction</code> is <code>Direction.HORIZONTAL</code>, |
| * then adjust the height of the tick marks. |
| * If <code>direction</code> is <code>Direction.VERTICAL</code>, |
| * then adjust the width. |
| * |
| * @default 3 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tickLength", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The y-position offset (if direction is horizontal) |
| * or x-position offset (if direction is vertical) |
| * of the tick marks relative to the track. |
| * |
| * @default -6 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tickOffset", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The thickness in pixels of the tick marks. |
| * If direction is horizontal, |
| * then adjust the width of the tick marks. |
| * If direction is vertical, |
| * then adjust the height. |
| * |
| * @default 1 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tickThickness", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The colors of the track, as an array of two colors. |
| * You can use the same color twice for a solid track color. |
| * |
| * <p>You use this property along with the <code>fillAlphas</code> |
| * property. Typically you set <code>fillAlphas</code> to [ 1.0, 1.0 ] |
| * when setting <code>trackColors</code>.</p> |
| * |
| * @default [ 0xE7E7E7, 0xE7E7E7 ] |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="trackColors", type="Array", arrayType="uint", format="Color", inherit="no", theme="halo")] |
| |
| /** |
| * Specifies whether to enable track highlighting between thumbs |
| * (or a single thumb and the beginning of the track). |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="showTrackHighlight", type="Boolean", inherit="no")] |
| |
| /** |
| * The size of the track margins, in pixels. |
| * If <code>undefined</code>, then the track margins will be determined |
| * by the length of the first and last labels. |
| * If given a value, Flex attempts to fit the labels in the available space. |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="trackMargin", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The name of the style declaration to use for the data tip. |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="dataTipStyleName", type="String", inherit="no")] |
| |
| /** |
| * The offset, in pixels, of the data tip relative to the thumb. |
| * Used in combination with the <code>dataTipPlacement</code> |
| * style property of the HSlider and VSlider controls. |
| * |
| * @default 16 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="dataTipOffset", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * Number of decimal places to use for the data tip text. |
| * A value of 0 means to round all values to an integer. |
| * |
| * @default 2 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="dataTipPrecision", type="int", inherit="no")] |
| |
| /** |
| * The default skin for the slider thumb. |
| * |
| * @default SliderThumbSkin |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="thumbSkin", type="Class", inherit="no", states="up, over, down, disabled")] |
| |
| /** |
| * The skin for the slider thumb up state. |
| * |
| * @default SliderThumbSkin |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="thumbUpSkin", type="Class", inherit="no")] |
| |
| /** |
| * The skin for the slider thumb over state. |
| * |
| * @default SliderThumbSkin |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="thumbOverSkin", type="Class", inherit="no")] |
| |
| /** |
| * The skin for the slider thumb down state. |
| * |
| * @default SliderThumbSkin |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="thumbDownSkin", type="Class", inherit="no")] |
| |
| /** |
| * The skin for the slider thumb disabled state. |
| * |
| * @default SliderThumbSkin |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="thumbDisabledSkin", type="Class", inherit="no")] |
| |
| /** |
| * The skin for the slider track when it is selected. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="trackHighlightSkin", type="Class", inherit="no")] |
| |
| /** |
| * The skin for the slider track. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="trackSkin", type="Class", inherit="no")] |
| |
| //-------------------------------------- |
| // Other metadata |
| //-------------------------------------- |
| |
| [AccessibilityClass(implementation="mx.accessibility.SliderAccImpl")] |
| |
| [ResourceBundle("SharedResources")] |
| |
| /** |
| * The Slider class is the base class for the Flex slider controls. |
| * The slider controls let 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 Slider class is subclassed by HSlider and VSlider. |
| * |
| * @mxml |
| * |
| * <p>The Slider class cannot be used as an MXML tag. Use the <code><mx:HSlider></code> |
| * and <code><mx:VSlider></code> tags instead. However, the Slider class does define tag |
| * attributes used by the <code><mx:HSlider></code> and <code><mx:VSlider></code> tags. </p> |
| * |
| * <p>The Slider class inherits all of the tag attributes |
| * of its superclass, and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <mx:<i>tagname</i> |
| * <strong>Properties</strong> |
| * allowThumbOverlap="false|true" |
| * allowTrackClick="true|false" |
| * dataTipFormatFunction="undefined" |
| * direction="horizontal|vertical" |
| * labels="undefined" |
| * liveDragging="false|true" |
| * maximum="10" |
| * minimum="0" |
| * showDataTip="true|false" |
| * sliderDataTipClass="sliderDataTip" |
| * sliderThumbClass="SliderThumb" |
| * snapInterval="0" |
| * thumbCount="1" |
| * tickInterval="0" |
| * tickValues="undefined" |
| * value="<i>The value of the minimum property.</i>" |
| * |
| * <strong>Styles</strong> |
| * borderColor="0x919999" |
| * dataTipOffset="16" |
| * dataTipPrecision="2" |
| * dataTipStyleName="undefined" |
| * fillAlphas="[0.6, 0.4, 0.75, 0.65]" |
| * fillColors="[0xFFFFFF, 0xCCCCCC, 0xFFFFFF, 0xEEEEEE;]" |
| * labelOffset="-10" |
| * labelStyleName="undefined" |
| * showTrackHighlight="false" |
| * slideDuration="300" |
| * slideEasingFunction="undefined" |
| * thumbDisabledSkin="SliderThumbSkin" |
| * thumbDownSkin="SliderThumbSkin" |
| * thumbOffset="0" |
| * thumbOverSkin="SliderThumbSkin" |
| * thumbUpSkin="SliderThumbSkin" |
| * tickColor="0x6F7777" |
| * tickLength="3" |
| * tickOffset="-6" |
| * tickThickness="1" |
| * trackColors="[ 0xEEEEEE, 0xFFFFFF ]" |
| * tracHighlightSkin="SliderHighlightSkin" |
| * trackMargin="undefined" |
| * trackSkin="SliderTrackSkin" |
| * |
| * <strong>Events</strong> |
| * change="<i>No default</i>" |
| * thumbDrag="<i>No default</i>" |
| * thumbPress="<i>No default</i>" |
| * thumbRelease="<i>No default</i>" |
| * /> |
| * </pre> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class Slider extends UIComponent |
| { |
| include "../../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class mixins |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Placeholder for mixin by SliderAccImpl. |
| */ |
| mx_internal static var createAccessibilityImplementation:Function; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function Slider() |
| { |
| super(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var track:IFlexDisplayObject; |
| |
| /** |
| * @private |
| */ |
| private var thumbs:UIComponent; |
| |
| /** |
| * @private |
| */ |
| private var thumbsChanged:Boolean = true; |
| |
| /** |
| * @private |
| */ |
| private var ticks:UIComponent; |
| |
| /** |
| * @private |
| */ |
| private var ticksChanged:Boolean = false; |
| |
| /** |
| * @private |
| */ |
| private var labelObjects:UIComponent; |
| |
| /** |
| * @private |
| */ |
| private var highlightTrack:IFlexDisplayObject; |
| |
| /** |
| * @private |
| */ |
| mx_internal var innerSlider:UIComponent; |
| |
| /** |
| * @private |
| */ |
| private var trackHitArea:UIComponent; |
| |
| /** |
| * @private |
| */ |
| mx_internal var dataTip:SliderDataTip; |
| |
| /** |
| * @private |
| */ |
| private var trackHighlightChanged:Boolean = true; |
| |
| /** |
| * @private |
| */ |
| private var initValues:Boolean = true; // Always initValues at startup |
| |
| /** |
| * @private |
| */ |
| private var dataFormatter:NumberFormatter; |
| |
| /** |
| * @private |
| */ |
| private var interactionClickTarget:String; |
| |
| /** |
| * @private |
| */ |
| private var labelStyleChanged:Boolean = false; |
| |
| /** |
| * @private |
| * is the last interaction from the keyboard? |
| */ |
| mx_internal var keyInteraction:Boolean = false; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // baselinePosition |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get baselinePosition():Number |
| { |
| if (!validateBaselinePosition()) |
| return NaN; |
| |
| return int(0.75 * height); |
| } |
| |
| //---------------------------------- |
| // enabled |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _enabled:Boolean; |
| |
| /** |
| * @private |
| */ |
| private var enabledChanged:Boolean = false; |
| |
| [Inspectable(category="General", enumeration="true,false", defaultValue="true")] |
| |
| /** |
| * @private |
| */ |
| override public function get enabled():Boolean |
| { |
| return _enabled; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set enabled(value:Boolean):void |
| { |
| _enabled = value; |
| enabledChanged = true; |
| |
| invalidateProperties(); |
| } |
| |
| /** |
| * @private |
| */ |
| private var _tabIndex:Number; |
| |
| /** |
| * @private |
| */ |
| private var tabIndexChanged:Boolean; |
| |
| /** |
| * @private |
| */ |
| override public function set tabIndex(value:int):void |
| { |
| super.tabIndex = value; |
| _tabIndex = value; |
| |
| tabIndexChanged = true; |
| invalidateProperties(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // allowThumbOverlap |
| //---------------------------------- |
| |
| [Inspectable(defaultValue="false")] |
| |
| /** |
| * If set to <code>false</code>, then each thumb can only be moved to the edge of |
| * the adjacent thumb. |
| * If <code>true</code>, then each thumb can be moved to any position on the track. |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var allowThumbOverlap:Boolean = false; |
| |
| //---------------------------------- |
| // allowTrackClick |
| //---------------------------------- |
| |
| [Inspectable(defaultValue="true")] |
| |
| /** |
| * Specifies whether clicking on the track will move the slider thumb. |
| * |
| * @default true |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var allowTrackClick:Boolean = true; |
| |
| //---------------------------------- |
| // 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):String |
| * </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 Slider Control named 'slide': </p> |
| * |
| * <pre> |
| * import mx.formatters.NumberBase; |
| * function myDataTipFormatter(value:Number):String { |
| * var dataFormatter:NumberBase = new NumberBase(".", ",", ".", ""); |
| * return "$ " + dataFormatter.formatPrecision(String(value), slide.getStyle("dataTipPrecision")); |
| * } |
| * </pre> |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get dataTipFormatFunction():Function |
| { |
| return _dataTipFormatFunction; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set dataTipFormatFunction(value:Function):void |
| { |
| _dataTipFormatFunction = value; |
| } |
| |
| //---------------------------------- |
| // direction |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _direction:String = SliderDirection.HORIZONTAL; |
| |
| /** |
| * @private |
| */ |
| private var directionChanged:Boolean = false; |
| |
| [Inspectable(defaultValue="horizontal")] |
| |
| /** |
| * The orientation of the slider control. |
| * Valid values in MXML are <code>"horizontal"</code> or <code>"vertical"</code>. |
| * |
| * <p>In ActionScript, you use the following constants |
| * to set this property: |
| * <code>SliderDirection.VERTICAL</code> and |
| * <code>SliderDirection.HORIZONTAL</code>.</p> |
| * |
| * The HSlider and VSlider controls set this property for you; |
| * do not set it when using those controls. |
| * |
| * @default SliderDirection.HORIZONTAL |
| * @see mx.controls.sliderClasses.SliderDirection |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get direction():String |
| { |
| return _direction; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set direction(value:String):void |
| { |
| _direction = value; |
| directionChanged = true; |
| |
| invalidateProperties(); |
| invalidateSize(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // labels |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _labels:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var labelsChanged:Boolean = false; |
| |
| [Inspectable(category="General", arrayType="String", defaultValue="undefined")] |
| |
| /** |
| * An array of strings used for the slider labels. |
| * Flex positions the labels at the beginning of the track, |
| * and spaces them evenly between the beginning of the track |
| * and the end of the track. |
| * |
| * <p>For example, if the array contains three items, |
| * the first item is placed at the beginning of the track, |
| * the second item in the middle, and the last item |
| * at the end of the track.</p> |
| * |
| * <p>If only one label is specified, it is placed at the |
| * beginning of the track. |
| * By default, labels are placed above the tick marks |
| * (if present) or above the track. |
| * To align the labels with the tick marks, make sure that |
| * the number of tick marks is equal to the number of labels.</p> |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get labels():Array |
| { |
| return _labels; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set labels(value:Array):void |
| { |
| _labels = value; |
| labelsChanged = true; |
| |
| invalidateProperties(); |
| invalidateSize(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // liveDragging |
| //---------------------------------- |
| |
| [Inspectable(category="General", defaultValue="false")] |
| |
| /** |
| * Specifies whether live dragging is enabled for the slider. |
| * If <code>false</code>, Flex sets the <code>value</code> and |
| * <code>values</code> properties and dispatches the <code>change</code> |
| * event when the user stops dragging the slider thumb. |
| * If <code>true</code>, Flex sets the <code>value</code> and |
| * <code>values</code> properties and dispatches the <code>change</code> |
| * event continuously as the user moves the thumb. |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var liveDragging:Boolean = false; |
| |
| //---------------------------------- |
| // maximum |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the maximum property. |
| */ |
| private var _maximum:Number = 10; |
| |
| [Inspectable(category="General", defaultValue="10")] |
| |
| /** |
| * The maximum allowed value on the slider. |
| * |
| * @default 10 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get maximum():Number |
| { |
| return _maximum; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set maximum(value:Number):void |
| { |
| _maximum = value; |
| ticksChanged = true; |
| if (!initValues) |
| valuesChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // minimum |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the minimum property. |
| */ |
| private var _minimum:Number = 0; |
| |
| /** |
| * @private |
| */ |
| private var minimumSet:Boolean = false; |
| |
| [Inspectable(category="General", defaultValue="0")] |
| |
| /** |
| * The minimum allowed value on the slider control. |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get minimum():Number |
| { |
| return _minimum; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set minimum(value:Number):void |
| { |
| _minimum = value; |
| ticksChanged = true; |
| |
| if (!initValues) |
| valuesChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // showDataTip |
| //---------------------------------- |
| |
| [Inspectable(category="General", defaultValue="true")] |
| |
| /** |
| * If set to <code>true</code>, show a data tip during user interaction |
| * containing the current value of the slider. |
| * |
| * @default true |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var showDataTip:Boolean = true; |
| |
| //---------------------------------- |
| // sliderThumbClass |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _thumbClass:Class = SliderThumb; |
| |
| /** |
| * A reference to the class to use for each thumb. |
| * |
| * @default SliderThumb |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get sliderThumbClass():Class |
| { |
| return _thumbClass; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set sliderThumbClass(value:Class):void |
| { |
| _thumbClass = value; |
| thumbsChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // sliderDataTipClass |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _sliderDataTipClass:Class = SliderDataTip; |
| |
| /** |
| * A reference to the class to use for the data tip. |
| * |
| * @default SliderDataTip |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get sliderDataTipClass():Class |
| { |
| return _sliderDataTipClass; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set sliderDataTipClass(value:Class):void |
| { |
| _sliderDataTipClass = value; |
| |
| invalidateProperties(); |
| } |
| |
| //---------------------------------- |
| // snapInterval |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _snapInterval:Number = 0; |
| |
| /** |
| * @private |
| */ |
| private var snapIntervalPrecision:int = -1; |
| |
| /** |
| * @private |
| */ |
| private var snapIntervalChanged:Boolean = false; |
| |
| [Inspectable(category="General", defaultValue="0")] |
| |
| /** |
| * Specifies the increment value of the slider thumb |
| * as the user moves the thumb. |
| * For example, if <code>snapInterval</code> is 2, |
| * the <code>minimum</code> value is 0, |
| * and the <code>maximum</code> value is 10, |
| * the thumb snaps to the values 0, 2, 4, 6, 8, and 10 |
| * as the user move the thumb. |
| * A value of 0, means that the slider moves continuously |
| * between the <code>minimum</code> and <code>maximum</code> values. |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get snapInterval():Number |
| { |
| return _snapInterval; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set snapInterval(value:Number):void |
| { |
| _snapInterval = value; |
| |
| var parts:Array = (new String(1 + value)).split("."); |
| if (parts.length == 2) |
| snapIntervalPrecision = parts[1].length; |
| else |
| snapIntervalPrecision = -1; |
| |
| if (!isNaN(value) && value != 0) |
| { |
| snapIntervalChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| } |
| |
| //---------------------------------- |
| // thumbCount |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the thumbCount property. |
| */ |
| private var _thumbCount:int = 1; |
| |
| [Inspectable(category="General", defaultValue="1")] |
| |
| /** |
| * The number of thumbs allowed on the slider. |
| * Possible values are 1 or 2. |
| * If set to 1, then the <code>value</code> property contains |
| * the current value of the slider. |
| * If set to 2, then the <code>values</code> property contains |
| * an array of values representing the value for each thumb. |
| * |
| * @default 1 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get thumbCount():int |
| { |
| return _thumbCount; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set thumbCount(value:int):void |
| { |
| var numThumbs:int = (value > 2) ? 2 : value; |
| numThumbs = value < 1 ? 1 : value; |
| |
| if (numThumbs != _thumbCount) |
| { |
| _thumbCount = numThumbs; |
| thumbsChanged = true; |
| |
| initValues = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| } |
| |
| //---------------------------------- |
| // thumbStyleFilters |
| //---------------------------------- |
| |
| /** |
| * Set of styles to pass from the Slider to the thumbs. |
| * @see mx.styles.StyleProxy |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function get thumbStyleFilters():Object |
| { |
| return null; |
| } |
| //---------------------------------- |
| // tickInterval |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _tickInterval:Number = 0; |
| |
| [Inspectable(category="General", defaultValue="0")] |
| |
| /** |
| * The spacing of the tick marks relative to the <code>maximum</code> value |
| * of the control. |
| * Flex displays tick marks whenever you set the <code>tickInterval</code> |
| * property to a nonzero value. |
| * |
| * <p>For example, if <code>tickInterval</code> is 1 and |
| * <code>maximum</code> is 10, then a tick mark is placed at each |
| * 1/10th interval along the slider. |
| * A value of 0 shows no tick marks. If the <code>tickValues</code> property |
| * is set to a non-empty Array, then this property is ignored.</p> |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get tickInterval():Number |
| { |
| return _tickInterval; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set tickInterval(value:Number):void |
| { |
| _tickInterval = value; |
| ticksChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| |
| //---------------------------------- |
| // tickValues |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _tickValues:Array = []; |
| |
| [Inspectable(category="General", defaultValue="undefined", arrayType="Number")] |
| |
| /** |
| * The positions of the tick marks on the slider. The positions correspond |
| * to the values on the slider and should be between |
| * the <code>minimum</code> and <code>maximum</code> values. |
| * For example, if the <code>tickValues</code> property |
| * is [0, 2.5, 7.5, 10] and <code>maximum</code> is 10, then a tick mark is placed |
| * in the following positions along the slider: the beginning of the slider, |
| * 1/4 of the way in from the left, |
| * 3/4 of the way in from the left, and at the end of the slider. |
| * |
| * <p>If this property is set to a non-empty Array, then the <code>tickInterval</code> property |
| * is ignored.</p> |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get tickValues():Array |
| { |
| return _tickValues; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set tickValues(value:Array):void |
| { |
| _tickValues = value; |
| ticksChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // value |
| //---------------------------------- |
| |
| [Bindable("change")] |
| [Bindable("valueCommit")] |
| [Inspectable(category="General", defaultValue="undefined")] |
| |
| /** |
| * Contains the position of the thumb, and is a number between the |
| * <code>minimum</code> and <code>maximum</code> properties. |
| * Use the <code>value</code> property when <code>thumbCount</code> is 1. |
| * When <code>thumbCount</code> is greater than 1, use the |
| * <code>values</code> property instead. |
| * The default value is equal to the minimum property. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get value():Number |
| { |
| return _values[0]; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set value(val:Number):void |
| { |
| setValueAt(val, 0, true); |
| valuesChanged = true; |
| minimumSet = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| |
| dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); |
| } |
| |
| //---------------------------------- |
| // values |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _values:Array = [ 0, 0 ]; |
| |
| /** |
| * @private |
| */ |
| private var valuesChanged:Boolean = false; |
| |
| [Bindable("change")] |
| [Inspectable(category="General", arrayType="Number")] |
| |
| /** |
| * An array of values for each thumb when <code>thumbCount</code> |
| * is greater than 1. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get values():Array |
| { |
| return _values; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set values(value:Array):void |
| { |
| _values = value; |
| valuesChanged = true; |
| minimumSet = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function initializeAccessibility():void |
| { |
| if (Slider.createAccessibilityImplementation != null) |
| Slider.createAccessibilityImplementation(this); |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function createChildren():void |
| { |
| super.createChildren(); |
| |
| if (!innerSlider) |
| { |
| innerSlider = new UIComponent(); |
| UIComponent(innerSlider).tabChildren = true; |
| addChild(innerSlider); |
| } |
| |
| createBackgroundTrack(); |
| |
| if (!trackHitArea) |
| { |
| trackHitArea = new UIComponent(); |
| innerSlider.addChild(trackHitArea); // trackHitArea should always be on top |
| |
| trackHitArea.addEventListener(MouseEvent.MOUSE_DOWN, |
| track_mouseDownHandler); |
| } |
| |
| invalidateProperties(); // Force commitProperties to be called on instantiation |
| } |
| |
| /** |
| * @private |
| */ |
| override public function styleChanged(styleProp:String):void |
| { |
| var anyStyle:Boolean = styleProp == null || styleProp == "styleName"; |
| |
| super.styleChanged(styleProp); |
| |
| if (styleProp == "showTrackHighlight" || anyStyle) |
| { |
| trackHighlightChanged = true; |
| invalidateProperties(); |
| } |
| |
| if (styleProp == "trackHighlightSkin" || anyStyle) |
| { |
| if (innerSlider && highlightTrack) |
| { |
| innerSlider.removeChild(DisplayObject(highlightTrack)); |
| highlightTrack = null; |
| } |
| trackHighlightChanged = true; |
| invalidateProperties(); |
| } |
| |
| if (styleProp == "labelStyleName" || anyStyle) |
| { |
| labelStyleChanged = true; |
| invalidateProperties(); |
| } |
| |
| if (styleProp == "trackMargin" || anyStyle) |
| { |
| invalidateSize(); |
| } |
| |
| if (styleProp == "trackSkin" || anyStyle) |
| { |
| if (track) |
| { |
| innerSlider.removeChild(DisplayObject(track)); |
| track = null; |
| createBackgroundTrack(); |
| } |
| } |
| |
| invalidateDisplayList(); |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function commitProperties():void |
| { |
| super.commitProperties(); |
| |
| var n:int; |
| var i:int; |
| |
| if (trackHighlightChanged) |
| { |
| trackHighlightChanged = false; |
| |
| if (getStyle("showTrackHighlight")) |
| { |
| createHighlightTrack(); |
| } |
| else if (highlightTrack) |
| { |
| innerSlider.removeChild(DisplayObject(highlightTrack)); |
| highlightTrack = null; |
| } |
| } |
| |
| if (directionChanged) |
| { |
| directionChanged = false; |
| var isHorizontal:Boolean = _direction == SliderDirection.HORIZONTAL; |
| |
| if (isHorizontal) |
| { |
| DisplayObject(innerSlider).rotation = 0; |
| } |
| else |
| { |
| DisplayObject(innerSlider).rotation = -90; |
| innerSlider.y = unscaledHeight; |
| } |
| |
| if (labelObjects) |
| { |
| for (var labelIndex:int = labelObjects.numChildren - 1; labelIndex >= 0; labelIndex--) |
| { |
| var labelObj:SliderLabel = SliderLabel( |
| labelObjects.getChildAt(labelIndex)); |
| labelObj.rotation = isHorizontal ? 0 : 90; |
| } |
| } |
| } |
| |
| if (labelStyleChanged && !labelsChanged) |
| { |
| labelStyleChanged = false; |
| |
| if (labelObjects) |
| { |
| var labelStyleName:String = getStyle("labelStyleName"); |
| n = labelObjects.numChildren; |
| for (i = 0; i < n; i++) |
| { |
| ISimpleStyleClient(labelObjects.getChildAt(i)).styleName = labelStyleName; |
| } |
| } |
| } |
| |
| if (ticksChanged) |
| { |
| ticksChanged = false; |
| |
| createTicks(); |
| } |
| |
| if (labelsChanged) |
| { |
| labelsChanged = false; |
| |
| createLabels(); |
| } |
| |
| if (thumbsChanged) |
| { |
| thumbsChanged = false; |
| |
| createThumbs(); |
| } |
| |
| |
| if (initValues) |
| { |
| initValues = false; |
| |
| if (!valuesChanged) |
| { |
| var val:Number = minimum; |
| |
| n = _thumbCount; |
| for (i = 0; i < n; i++) |
| { |
| _values[i] = val; |
| setValueAt(val, i); |
| if (_snapInterval && _snapInterval != 0) |
| val += snapInterval; |
| else |
| val++; |
| } |
| |
| snapIntervalChanged = false; |
| } |
| } |
| |
| if (snapIntervalChanged) |
| { |
| snapIntervalChanged = false; |
| |
| if (!valuesChanged) |
| { |
| n = thumbs.numChildren; |
| for (i = 0; i < n; i++) |
| { |
| setValueAt(getValueFromX(SliderThumb(thumbs.getChildAt(i)).xPosition), i); |
| } |
| } |
| } |
| |
| |
| |
| if (valuesChanged) |
| { |
| valuesChanged = false; |
| |
| n = _thumbCount; |
| for (i = 0; i < n; i++) |
| { |
| setValueAt(getValueFromX(getXFromValue(Math.min(Math.max(values[i], minimum), maximum))), i); |
| } |
| } |
| |
| if (enabledChanged) |
| { |
| enabledChanged = false; |
| |
| n = thumbs.numChildren; |
| for (i = 0; i < n; i++) |
| { |
| SliderThumb(thumbs.getChildAt(i)).enabled = enabled; |
| } |
| |
| n = labelObjects ? labelObjects.numChildren : 0; |
| for (i = 0; i < n; i++) |
| { |
| SliderLabel(labelObjects.getChildAt(i)).enabled = enabled; |
| } |
| |
| if (track is IUIComponent) |
| IUIComponent(track).enabled = enabled; |
| |
| if (highlightTrack && highlightTrack is IUIComponent) |
| IUIComponent(highlightTrack).enabled = enabled; |
| } |
| |
| if (tabIndexChanged) |
| { |
| tabIndexChanged = false; |
| |
| n = thumbs.numChildren; |
| for (i = 0; i < n; i++) |
| { |
| SliderThumb(thumbs.getChildAt(i)).tabIndex = _tabIndex; |
| } |
| } |
| } |
| |
| /** |
| * Calculates the amount of space that the component takes up. |
| * A horizontal slider control calculates its height by examining |
| * the position of its labels, tick marks, and thumbs |
| * relative to the track. |
| * The height of the control is equivalent to the position |
| * of the bottom of the lowest element subtracted |
| * from the position of the top of the highest element. |
| * The width of a horizontal slider control defaults to 250 pixels. |
| * For a vertical slider control, the width and the length |
| * measurements are reversed. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function measure():void |
| { |
| super.measure(); |
| |
| var isHorizontal:Boolean = (direction == SliderDirection.HORIZONTAL); |
| var numLabels:int = labelObjects ? labelObjects.numChildren : 0; |
| var trackMargin:Number = getStyle("trackMargin"); |
| var length:Number = DEFAULT_MEASURED_WIDTH; |
| |
| if (!isNaN(trackMargin)) |
| { |
| if (numLabels > 0) |
| { |
| length += (isHorizontal ? |
| SliderLabel(labelObjects.getChildAt(0)).getExplicitOrMeasuredWidth() / 2 : |
| SliderLabel(labelObjects.getChildAt(0)).getExplicitOrMeasuredHeight() / 2); |
| } |
| if (numLabels > 1) |
| { |
| length += (isHorizontal ? |
| SliderLabel(labelObjects.getChildAt(numLabels - 1)).getExplicitOrMeasuredWidth() / 2 : |
| SliderLabel(labelObjects.getChildAt(numLabels - 1)).getExplicitOrMeasuredHeight() / 2); |
| } |
| //length += track.width; |
| } |
| |
| var bounds:Object = getComponentBounds(); |
| var thickness:Number = bounds.lower - bounds.upper; |
| |
| measuredMinWidth = measuredWidth = isHorizontal ? length : thickness; |
| measuredMinHeight = measuredHeight = isHorizontal ? thickness : length; |
| } |
| |
| /** |
| * Positions the elements of the control. |
| * The track, thumbs, labels, and tick marks are all positioned |
| * and sized by this method. |
| * The track is sized based on the length of the labels and on the track margin. |
| * If you specify a <code>trackMargin</code>, then the size of the track |
| * is equal to the available width minus the <code>trackMargin</code> times 2. |
| * |
| * <p>Tick marks are spaced at even intervals along the track starting from the beginning of the track. An additional tick mark is placed |
| * at the end of the track if one doesn't already exist (if the tick interval isn't a factor of the maximum value). The tick mark |
| * y-position is based on the <code>tickOffset</code>. An offset of 0 places the bottom of the tick at the top of the track. Negative offsets |
| * move the ticks upwards while positive offsets move them downward through the track.</p> |
| * |
| * <p>Labels are positioned at even intervals along the track. The labels are always horizontally centered above their |
| * interval position unless the <code>trackMargin</code> setting is too small. If you specify a <code>trackMargin</code>, then the first and last labels will |
| * position themselves at the left and right borders of the control. Labels will not crop or resize themselves if they overlap, |
| * so be sure to allow enough space for them to fit on the track. The y-position is based on the <code>labelOffset</code> property. An offset of 0 |
| * places the bottom of the label at the top of the track. Unlike tick marks, the labels can not be positioned to overlap the track. |
| * If the offset is a positive number, then the top of the label will be positioned below the bottom of the track.</p> |
| * |
| * <p>The thumbs are positioned to overlap the track. Their x-position is determined by their value. The y-position is |
| * controlled by the <code>thumbOffset</code> property. An offset of 0 places the center of the thumb at the center of the track. A negative |
| * offset moves the thumbs upwards while a positive offset moves the thumbs downwards.</p> |
| * |
| * <p>The placement of the tick marks, labels and thumbs are all independent from each other. They will not attempt to reposition |
| * themselves if they overlap.</p> |
| * |
| * <p>For a vertical slider control, the same rules apply. In the above description, substitute width for height, height for width, |
| * left for up or top, right for down or bottom, x-position for y-position, and y-position for x-position.</p> |
| * |
| * @param unscaledWidth Specifies the width of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleX</code> property of the component. |
| * |
| * @param unscaledHeight Specifies the height of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleY</code> property of the component. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function updateDisplayList(unscaledWidth:Number, |
| unscaledHeight:Number):void |
| { |
| super.updateDisplayList(unscaledWidth, unscaledHeight); |
| |
| // graphics.beginFill(0xEEEEEE); |
| // graphics.drawRect(0, 0, unscaledWidth, unscaledHeight); |
| // graphics.endFill(); |
| |
| var isHorizontal:Boolean = (_direction == SliderDirection.HORIZONTAL); |
| var numLabels:int = labelObjects ? labelObjects.numChildren : 0; |
| var trackMargin:Number = getStyle("trackMargin"); |
| var firstThumbWidth:Number = 6; |
| var firstThumbHeight:Number = 0; |
| var firstThumb:SliderThumb; |
| |
| if (thumbs && thumbs.numChildren > 0) |
| firstThumb = SliderThumb(thumbs.getChildAt(0)); |
| |
| if (thumbs && firstThumb) { |
| firstThumbWidth = firstThumb.getExplicitOrMeasuredWidth(); |
| firstThumbHeight = firstThumb.getExplicitOrMeasuredHeight(); |
| } |
| |
| var trackLeftOffset:Number = firstThumbWidth / 2; // Enough space for the thumb to rest at the edges |
| var trackRightOffset:Number = trackLeftOffset; |
| |
| var availSpace:Number; |
| |
| var firstLabelSize:Number = 0; |
| if (numLabels > 0) |
| { |
| var firstLabel:SliderLabel = |
| SliderLabel(labelObjects.getChildAt(0)); |
| |
| firstLabelSize = isHorizontal ? |
| firstLabel.getExplicitOrMeasuredWidth() : |
| firstLabel.getExplicitOrMeasuredHeight(); |
| } |
| |
| var lastLabelSize:Number = 0; |
| if (numLabels > 1) |
| { |
| var lastLabel:SliderLabel = |
| SliderLabel(labelObjects.getChildAt(numLabels - 1)); |
| lastLabelSize = isHorizontal ? |
| lastLabel.getExplicitOrMeasuredWidth(): |
| lastLabel.getExplicitOrMeasuredHeight(); |
| } |
| |
| if (!isNaN(trackMargin)) |
| availSpace = trackMargin; |
| else |
| availSpace = (firstLabelSize + lastLabelSize) / 2; |
| |
| if (numLabels > 0) |
| { |
| if (!isNaN(trackMargin)) |
| { |
| trackLeftOffset = Math.max(trackLeftOffset, |
| availSpace / (numLabels > 1 ? 2 : 1)); |
| } |
| else |
| { |
| trackLeftOffset = Math.max(trackLeftOffset, firstLabelSize / 2); |
| } |
| } |
| else |
| { |
| |
| trackLeftOffset = Math.max(trackLeftOffset, availSpace / 2); |
| } |
| |
| var bounds:Object = getComponentBounds(); |
| |
| //track.x = Math.round(trackLeftOffset); |
| |
| var trackY:Number = (((isHorizontal ? unscaledHeight : unscaledWidth) - |
| (Number(bounds.lower) - Number(bounds.upper))) / 2) - Number(bounds.upper); |
| |
| track.move(Math.round(trackLeftOffset), Math.round(trackY)); |
| track.setActualSize((isHorizontal ? unscaledWidth: unscaledHeight) - (trackLeftOffset * 2), track.height); |
| |
| // Layout the thumbs' y positions. |
| var tY:Number = track.y + |
| (track.height - firstThumbHeight) / 2 + |
| getStyle("thumbOffset"); |
| |
| var n:int = _thumbCount; |
| for (var i:int = 0; i < n; i++) |
| { |
| var currentThumb:SliderThumb = SliderThumb(thumbs.getChildAt(i)); |
| currentThumb.move(currentThumb.x, tY); |
| currentThumb.visible = true; |
| currentThumb.setActualSize(currentThumb.getExplicitOrMeasuredWidth(), |
| currentThumb.getExplicitOrMeasuredHeight()); |
| } |
| |
| var g:Graphics = trackHitArea.graphics; |
| |
| var tLength:Number = 0 |
| if (_tickInterval > 0 || (_tickValues && _tickValues.length > 0)) |
| tLength = getStyle("tickLength"); |
| g.clear(); |
| g.beginFill(0,0); |
| g.drawRect(track.x, |
| track.y - firstThumbHeight/2 - tLength, |
| track.width, |
| track.height + firstThumbHeight + tLength); |
| g.endFill(); |
| |
| if (_direction != SliderDirection.HORIZONTAL) |
| innerSlider.y = unscaledHeight; |
| |
| layoutTicks(); |
| |
| layoutLabels(); |
| |
| setPosFromValue(); // use the value to position the thumb's x |
| |
| drawTrackHighlight(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private function createBackgroundTrack():void |
| { |
| if (!track) |
| { |
| var trackSkinClass:Class = getStyle("trackSkin"); |
| |
| track = new trackSkinClass(); |
| |
| if (track is ISimpleStyleClient) |
| ISimpleStyleClient(track).styleName = this; |
| |
| if (track is IUIComponent) |
| IUIComponent(track).enabled = enabled; |
| |
| innerSlider.addChildAt(DisplayObject(track),0); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function createHighlightTrack():void |
| { |
| var showTrackHighlight:Boolean = getStyle("showTrackHighlight"); |
| if (!highlightTrack && showTrackHighlight) |
| { |
| var trackHighlightClass:Class = |
| getStyle("trackHighlightSkin"); |
| highlightTrack = new trackHighlightClass(); |
| |
| if (highlightTrack is ISimpleStyleClient) |
| ISimpleStyleClient(highlightTrack).styleName = this; |
| |
| if (highlightTrack is IUIComponent) |
| IUIComponent(highlightTrack).enabled = enabled; |
| |
| innerSlider.addChildAt(DisplayObject(highlightTrack), |
| innerSlider.getChildIndex(DisplayObject(track)) + 1); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function createThumbs():void |
| { |
| var n:int; |
| var i:int; |
| |
| // Delete all thumb children |
| if (thumbs) |
| { |
| n = thumbs.numChildren; |
| for (i = n - 1; i >= 0; i--) |
| { |
| // we don't need to bother to remove the event listeners here |
| // they will be removed by the garbage collector automatically |
| thumbs.removeChildAt(i); |
| } |
| } |
| else |
| { |
| thumbs = new UIComponent(); |
| thumbs.tabChildren = true; |
| thumbs.tabEnabled = false; |
| thumbs.tabFocusEnabled = false; |
| innerSlider.addChild(thumbs); |
| } |
| |
| var thumb:SliderThumb; // We want to force the thumb to be a subclass of SliderThumb |
| |
| n = _thumbCount; |
| for (i = 0; i < n; i++) |
| { |
| thumb = SliderThumb(new _thumbClass()); |
| |
| thumb.owner = this; |
| thumb.styleName = new StyleProxy(this, thumbStyleFilters); |
| thumb.thumbIndex = i; |
| thumb.visible = true; |
| thumb.enabled = enabled; |
| |
| thumb.upSkinName = "thumbUpSkin"; |
| thumb.downSkinName = "thumbDownSkin"; |
| thumb.disabledSkinName = "thumbDisabledSkin"; |
| thumb.overSkinName = "thumbOverSkin"; |
| thumb.skinName = "thumbSkin"; |
| |
| thumbs.addChild(thumb); |
| |
| thumb.addEventListener(FocusEvent.FOCUS_IN, |
| thumb_focusInHandler); |
| thumb.addEventListener(FocusEvent.FOCUS_OUT, |
| thumb_focusOutHandler); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function createLabels():void |
| { |
| var labelObj:SliderLabel; |
| |
| if (labelObjects) |
| { |
| for (var i:int = labelObjects.numChildren - 1; i >= 0; i--) |
| { |
| labelObjects.removeChildAt(i); |
| } |
| } |
| else |
| { |
| labelObjects = new UIComponent(); |
| innerSlider.addChildAt(labelObjects, innerSlider.getChildIndex(trackHitArea)); |
| } |
| |
| if (_labels) |
| { |
| var numLabels:int = _labels.length; |
| |
| for (var j:int = 0; j < numLabels; j++) |
| { |
| labelObj = new SliderLabel(); |
| |
| labelObj.text = _labels[j] is String ? |
| _labels[j] : |
| _labels[j].toString(); |
| |
| if (_direction != SliderDirection.HORIZONTAL) |
| labelObj.rotation = 90; |
| |
| var labelStyleName:String = getStyle("labelStyleName"); |
| if (labelStyleName) |
| labelObj.styleName = labelStyleName; |
| |
| labelObjects.addChild(labelObj); |
| } |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function createTicks():void |
| { |
| if (!ticks) |
| { |
| ticks = new UIComponent(); |
| |
| innerSlider.addChild(ticks); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function getComponentBounds():Object |
| { |
| var isHorizontal:Boolean = (direction == SliderDirection.HORIZONTAL); |
| var numLabels:int = labelObjects ? labelObjects.numChildren : 0; |
| var labelY:Number; |
| var labelSize:Number = 0; |
| var thumbY:Number; |
| var upperBound:Number = 0; |
| var lowerBound:Number = track.height; |
| |
| if (numLabels > 0) |
| { |
| var sliderLabel:SliderLabel = |
| SliderLabel(labelObjects.getChildAt(0)); |
| |
| if (isHorizontal) |
| { |
| labelSize = sliderLabel.getExplicitOrMeasuredHeight(); |
| } |
| else |
| { |
| for (var i:int = 0; i < numLabels; i++) |
| { |
| sliderLabel = SliderLabel(labelObjects.getChildAt(i)); |
| labelSize = Math.max(labelSize, |
| sliderLabel.getExplicitOrMeasuredWidth()); |
| } |
| } |
| |
| var labOffset:Number = getStyle("labelOffset"); |
| labelY = labOffset - (labOffset > 0 ? 0 : labelSize); |
| |
| upperBound = Math.min(upperBound, labelY); |
| lowerBound = Math.max(lowerBound, labOffset + (labOffset > 0 ? labelSize : 0)); |
| } |
| |
| if (ticks) |
| { |
| var tLen:Number = getStyle("tickLength"); |
| var tOff:Number = getStyle("tickOffset"); |
| |
| upperBound = Math.min(upperBound, tOff - tLen); |
| lowerBound = Math.max(lowerBound, tOff); |
| } |
| |
| if (thumbs && thumbs.numChildren > 0) |
| { |
| thumbY = (track.height - SliderThumb(thumbs.getChildAt(0)).getExplicitOrMeasuredHeight()) / 2 + |
| getStyle("thumbOffset"); |
| |
| upperBound = Math.min(upperBound, thumbY); |
| lowerBound = Math.max(lowerBound, thumbY + SliderThumb(thumbs.getChildAt(0)).getExplicitOrMeasuredHeight()); |
| } |
| |
| return { lower: lowerBound, upper: upperBound }; |
| } |
| |
| /** |
| * @private |
| */ |
| private function layoutTicks():void |
| { |
| if (ticks) |
| { |
| var g:Graphics = ticks.graphics; |
| var tLength:Number = getStyle("tickLength"); |
| var tOffset:Number = getStyle("tickOffset"); |
| var tickWidth:Number = getStyle("tickThickness"); |
| var xPos:Number; |
| var tColor:Number = getStyle("tickColor"); |
| |
| var usePositions:Boolean = _tickValues && _tickValues.length > 0 ? true : false; |
| var positionIndex:int = 0; |
| var val:Number = usePositions ? _tickValues[positionIndex++] : minimum; |
| |
| g.clear(); |
| |
| if (_tickInterval > 0 || usePositions) |
| { |
| g.lineStyle(tickWidth,tColor,100); |
| |
| do |
| { |
| xPos = Math.round(getXFromValue(val)); |
| g.moveTo(xPos, tLength); |
| g.lineTo(xPos, 0); |
| val = usePositions ? (positionIndex < _tickValues.length ? _tickValues[positionIndex++] : NaN) : _tickInterval + val; |
| } while (val < maximum || (usePositions && positionIndex < _tickValues.length)) |
| |
| // draw the last tick |
| if (!usePositions || val == maximum) |
| { |
| xPos = track.x + track.width - 1; |
| g.moveTo(xPos, tLength); |
| g.lineTo(xPos, 0); |
| } |
| |
| ticks.y = Math.round(track.y + tOffset - tLength); |
| } |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function layoutLabels():void |
| { |
| var numLabels:Number = labelObjects ? labelObjects.numChildren : 0; |
| var availSpace:Number; |
| |
| if (numLabels > 0) |
| { |
| var labelInterval:Number = track.width / (numLabels - 1); |
| // The amount of space we have available for the labels to hang past the track |
| availSpace = Math.max((_direction == SliderDirection.HORIZONTAL ? |
| unscaledWidth : |
| unscaledHeight) - track.width, |
| SliderThumb(thumbs.getChildAt(0)).getExplicitOrMeasuredWidth()); |
| |
| var labelPos:Number; |
| var left:Number = track.x; |
| var curLabel:Object; |
| |
| for (var i:int = 0; i < numLabels; i++) |
| { |
| curLabel = labelObjects.getChildAt(i); |
| curLabel.setActualSize(curLabel.getExplicitOrMeasuredWidth(), curLabel.getExplicitOrMeasuredHeight()); |
| |
| var yPos:Number = track.y - curLabel.height + getStyle("labelOffset"); |
| |
| if (_direction == SliderDirection.HORIZONTAL) |
| { |
| labelPos = curLabel.getExplicitOrMeasuredWidth() / 2; |
| |
| if (i == 0) |
| labelPos = Math.min(labelPos, availSpace / (numLabels > Number(1) ? Number(2) : Number(1))); |
| else if (i == (numLabels - 1)) |
| labelPos = Math.max(labelPos, curLabel.getExplicitOrMeasuredWidth() - availSpace / 2); |
| |
| curLabel.move(left - labelPos,yPos); |
| } |
| else |
| { |
| var labelOff:Number = getStyle("labelOffset"); |
| |
| labelPos = curLabel.getExplicitOrMeasuredHeight() / 2; |
| |
| if (i == 0) |
| labelPos = Math.max(labelPos, curLabel.getExplicitOrMeasuredHeight() - availSpace / (numLabels > Number(1) ? Number(2) : Number(1))); |
| else if (i == (numLabels-1)) |
| labelPos = Math.min(labelPos,availSpace / 2); |
| |
| curLabel.move(left + labelPos,track.y + labelOff + |
| (labelOff > 0 ? 0 : -curLabel.getExplicitOrMeasuredWidth())); |
| } |
| left += labelInterval; |
| } |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function drawTrackHighlight():void |
| { |
| if (highlightTrack) |
| { |
| var xPos:Number; |
| var tWidth:Number; |
| |
| var firstThumb:SliderThumb = SliderThumb(thumbs.getChildAt(0)); |
| |
| if (_thumbCount > 1) |
| { |
| xPos = firstThumb.xPosition; |
| var secondThumb:SliderThumb = SliderThumb(thumbs.getChildAt(1)); |
| tWidth = secondThumb.xPosition - firstThumb.xPosition; |
| } |
| else |
| { |
| xPos = track.x; |
| tWidth = firstThumb.xPosition - xPos; |
| } |
| |
| |
| highlightTrack.move(xPos, track.y + 1); |
| highlightTrack.setActualSize(tWidth > 0 ? tWidth : 0, highlightTrack.height); |
| } |
| } |
| |
| /** |
| * @private |
| * Helper function that starts the dataTip and dispatches the press event. |
| */ |
| mx_internal function onThumbPress(thumb:Object):void |
| { |
| if (showDataTip) |
| { |
| // Setup number formatter |
| dataFormatter = new NumberFormatter(); |
| dataFormatter.precision = getStyle("dataTipPrecision"); |
| |
| if (!dataTip) |
| { |
| dataTip = SliderDataTip(new sliderDataTipClass()); |
| systemManager.toolTipChildren.addChild(dataTip); |
| |
| var dataTipStyleName:String = getStyle("dataTipStyleName"); |
| if (dataTipStyleName) |
| { |
| dataTip.styleName = dataTipStyleName; |
| } |
| } |
| |
| var formattedVal:String; |
| if (_dataTipFormatFunction != null) |
| { |
| formattedVal = this._dataTipFormatFunction( |
| getValueFromX(thumb.xPosition)); |
| } |
| else |
| { |
| formattedVal = dataFormatter.format(getValueFromX(thumb.xPosition)); |
| } |
| |
| dataTip.text = formattedVal; |
| |
| // Tool tip has been freshly created and new text assigned to it. |
| // Hence force a validation so that we can set the |
| // size required to show the text completely. |
| dataTip.validateNow(); |
| dataTip.setActualSize(dataTip.getExplicitOrMeasuredWidth(),dataTip.getExplicitOrMeasuredHeight()); |
| positionDataTip(thumb); |
| } |
| keyInteraction = false; |
| |
| var event:SliderEvent = new SliderEvent(SliderEvent.THUMB_PRESS); |
| event.value = getValueFromX(thumb.xPosition);; |
| event.thumbIndex = thumb.thumbIndex; |
| dispatchEvent(event); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function onThumbRelease(thumb:Object):void |
| { |
| interactionClickTarget = SliderEventClickTarget.THUMB; |
| |
| destroyDataTip(); |
| |
| setValueFromPos(thumb.thumbIndex); |
| |
| dataFormatter = null; |
| |
| var event:SliderEvent = new SliderEvent(SliderEvent.THUMB_RELEASE); |
| event.value = getValueFromX(thumb.xPosition);; |
| event.thumbIndex = thumb.thumbIndex; |
| dispatchEvent(event); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function onThumbMove(thumb:Object):void |
| { |
| var value:Number = getValueFromX(thumb.xPosition); |
| |
| if (showDataTip) |
| { |
| dataTip.text = _dataTipFormatFunction != null ? |
| _dataTipFormatFunction(value) : |
| dataFormatter.format(value); |
| |
| dataTip.setActualSize(dataTip.getExplicitOrMeasuredWidth(), |
| dataTip.getExplicitOrMeasuredHeight()); |
| |
| positionDataTip(thumb); |
| } |
| |
| if (liveDragging) |
| { |
| interactionClickTarget = SliderEventClickTarget.THUMB; |
| setValueAt(value, thumb.thumbIndex); |
| } |
| |
| var event:SliderEvent = new SliderEvent(SliderEvent.THUMB_DRAG); |
| event.value = value; |
| event.thumbIndex = thumb.thumbIndex; |
| dispatchEvent(event); |
| } |
| |
| /** |
| * @private |
| */ |
| private function positionDataTip(thumb:Object):void |
| { |
| var relX:Number; |
| var relY:Number; |
| |
| var tX:Number = thumb.x; |
| var tY:Number = thumb.y; |
| |
| var tPlacement:String = getStyle("dataTipPlacement"); |
| var tOffset:Number = getStyle("dataTipOffset"); |
| |
| // If the layoutDirection is rtl, swap left and right placement |
| if (layoutDirection == LayoutDirection.RTL) |
| { |
| if (tPlacement == "left") |
| tPlacement = "right"; |
| else if (tPlacement == "right") |
| tPlacement = "left"; |
| } |
| |
| // Need to special case tooltip position because the tooltip movieclip |
| // resides in the root movie clip, instead of the Slider movieclip |
| if (_direction == SliderDirection.HORIZONTAL) |
| { |
| relX = tX; |
| relY = tY; |
| |
| if (tPlacement == "left") |
| { |
| relX -= tOffset + dataTip.width; |
| relY += (thumb.height - dataTip.height) / 2; |
| } |
| else if (tPlacement == "right") |
| { |
| relX += tOffset + thumb.width; |
| relY += (thumb.height - dataTip.height) / 2; |
| } |
| else if (tPlacement == "top") |
| { |
| relY -= tOffset + dataTip.height; |
| relX -= (dataTip.width - thumb.width) / 2; |
| } |
| else if (tPlacement == "bottom") |
| { |
| relY += tOffset + thumb.height; |
| relX -= (dataTip.width - thumb.width) / 2; |
| } |
| } |
| else |
| { |
| relX = tY; |
| relY = unscaledHeight - tX - (dataTip.height + thumb.width) / 2; |
| |
| if (tPlacement == "left") |
| { |
| relX -= tOffset + dataTip.width; |
| } |
| else if (tPlacement == "right") |
| { |
| relX += tOffset + thumb.height; |
| } |
| else if (tPlacement == "top") |
| { |
| relY -= tOffset + (dataTip.height + thumb.width) / 2; |
| relX -= (dataTip.width - thumb.height) / 2; |
| } |
| else if (tPlacement == "bottom") |
| { |
| relY += tOffset + (dataTip.height + thumb.width) / 2; |
| relX -= (dataTip.width - thumb.height) / 2; |
| } |
| } |
| |
| if (layoutDirection == LayoutDirection.RTL) |
| relX += dataTip.width; |
| |
| var o:Point = new Point(relX, relY); |
| var r:Point = localToGlobal(o); |
| r = dataTip.parent.globalToLocal(r); |
| |
| dataTip.x = r.x < 0 ? 0 : r.x; |
| dataTip.y = r.y < 0 ? 0 : r.y; |
| } |
| |
| /** |
| * @private |
| */ |
| private function destroyDataTip():void |
| { |
| if (dataTip) |
| { |
| systemManager.toolTipChildren.removeChild(dataTip); |
| dataTip = null; |
| } |
| } |
| |
| /** |
| * @private |
| * Utility for finding the x position which corresponds |
| * to the given value. |
| */ |
| mx_internal function getXFromValue(v:Number):Number |
| { |
| var val:Number; |
| |
| if (v == minimum) |
| val = track.x; |
| else if (v == maximum) |
| val = track.x + track.width; |
| else |
| val = track.x + (v - minimum) * (track.width) / (maximum - minimum); |
| |
| return val; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getXBounds(selectedThumbIndex:int):Object |
| { |
| var maxX:Number = track.x + track.width; |
| var minX:Number = track.x; |
| if (allowThumbOverlap) |
| { |
| return { max: maxX, min: minX }; |
| } |
| |
| var minBound:Number = NaN; |
| var maxBound:Number = NaN; |
| |
| var prevThumb:SliderThumb = |
| selectedThumbIndex > 0 ? |
| SliderThumb(thumbs.getChildAt(selectedThumbIndex - 1)) : |
| null; |
| |
| var nextThumb:SliderThumb = |
| selectedThumbIndex + 1 < thumbs.numChildren ? |
| SliderThumb(thumbs.getChildAt(selectedThumbIndex + 1)) : |
| null; |
| |
| if (prevThumb) |
| minBound = prevThumb.xPosition + prevThumb.width / 2; |
| |
| if (nextThumb) |
| maxBound = nextThumb.xPosition - nextThumb.width / 2; |
| |
| if (isNaN(minBound)) |
| minBound = minX; |
| else |
| minBound = Math.min(Math.max(minX,minBound),maxX); |
| |
| if (isNaN(maxBound)) |
| maxBound = maxX; |
| else |
| maxBound = Math.max(Math.min(maxX, maxBound),minX); |
| |
| return { max: maxBound, min: minBound }; |
| } |
| |
| /** |
| * @private |
| * Utility for positioning the thumb(s) from the current value. |
| */ |
| private function setPosFromValue():void |
| { |
| var n:int = _thumbCount; |
| for (var i:int = 0; i < n; i++) |
| { |
| var thumb:SliderThumb = SliderThumb(thumbs.getChildAt(i)); |
| thumb.xPosition = getXFromValue(values[i]); |
| } |
| } |
| |
| /** |
| * @private |
| * Utility for getting a value corresponding to a given x. |
| */ |
| mx_internal function getValueFromX(xPos:Number):Number |
| { |
| var v:Number = (xPos - track.x) * |
| (maximum - minimum) / |
| (track.width) + minimum; |
| |
| var threshold:Number = (maximum - minimum) / 1000; |
| |
| // kill rounding error at the edges. |
| if (v - minimum <= threshold) |
| { |
| v = minimum; |
| } |
| else if (maximum - v <= threshold) |
| { |
| v = maximum; |
| } |
| else if (!isNaN(_snapInterval) && _snapInterval != 0) |
| { |
| v = Math.round((v - minimum) / _snapInterval) * |
| _snapInterval + minimum; |
| } |
| |
| return v; |
| } |
| |
| /** |
| * @private |
| * Utility for committing a value of a given thumb. |
| */ |
| private function setValueFromPos(thumbIndex:int):void |
| { |
| var thumb:SliderThumb = SliderThumb(thumbs.getChildAt(thumbIndex)); |
| setValueAt(getValueFromX(thumb.xPosition), thumbIndex); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getSnapValue(value:Number, thumb:SliderThumb = null):Number |
| { |
| if (!isNaN(_snapInterval) && _snapInterval != 0) |
| { |
| var val:Number = getValueFromX(value); |
| |
| if (thumb && (thumbs.numChildren > 1) && !allowThumbOverlap) |
| { |
| var check_bounds:Boolean = true; |
| var bounds:Object |
| |
| bounds = getXBounds(thumb.thumbIndex); |
| |
| var prevThumb:SliderThumb = |
| thumb.thumbIndex > 0 ? |
| SliderThumb(thumbs.getChildAt(thumb.thumbIndex- 1)) : |
| null; |
| |
| var nextThumb:SliderThumb = |
| thumb.thumbIndex + 1 < thumbs.numChildren ? |
| SliderThumb(thumbs.getChildAt(thumb.thumbIndex + 1)) : |
| null; |
| |
| if (prevThumb) |
| { |
| bounds.min -= (prevThumb.width / 2); |
| // check if thumb is at minimum, if not we can ignore the bounds logic |
| if (val == minimum) |
| if (getValueFromX((prevThumb.xPosition - prevThumb.width/2)) != minimum) |
| check_bounds = false; |
| } |
| else |
| { |
| if (val == minimum) |
| check_bounds = false; |
| } |
| |
| if (nextThumb) |
| { |
| bounds.max += (nextThumb.width / 2); |
| // check if thumb is at maximum, if not we can ignore the bounds logic |
| if (val == maximum) |
| if (getValueFromX((nextThumb.xPosition + nextThumb.width/2)) != maximum) |
| check_bounds = false; |
| } |
| else |
| { |
| if (val == maximum) |
| check_bounds = false; |
| } |
| if (check_bounds) |
| val = Math.min(Math.max(val, getValueFromX(Math.round(bounds.min)) + _snapInterval), |
| getValueFromX(Math.round(bounds.max)) - _snapInterval); |
| |
| } |
| return getXFromValue(val); |
| } |
| |
| return value; |
| } |
| |
| /** |
| * @private Accessed by the Thumb to find out the snap interval |
| */ |
| mx_internal function getSnapIntervalWidth():Number |
| { |
| return _snapInterval * track.width / (maximum - minimum); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function updateThumbValue(thumbIndex:int):void |
| { |
| setValueFromPos(thumbIndex); |
| } |
| |
| /** |
| * Returns the thumb object at the given index. Use this method to |
| * style and customize individual thumbs in a slider control. |
| * |
| * @param index The zero-based index number of the thumb. |
| * |
| * @return A reference to the SliderThumb object. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getThumbAt(index:int):SliderThumb |
| { |
| return index >= 0 && index < thumbs.numChildren ? |
| SliderThumb(thumbs.getChildAt(index)) : |
| null; |
| } |
| |
| /** |
| * This method sets the value of a slider thumb, and updates the display. |
| * |
| * @param index The zero-based index number of the thumb to set |
| * the value of, where a value of 0 corresponds to the first thumb. |
| * |
| * @param value The value to set the thumb to |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function setThumbValueAt(index:int, value:Number):void |
| { |
| setValueAt(value, index, true); |
| valuesChanged = true; |
| |
| invalidateProperties(); |
| invalidateDisplayList(); |
| } |
| |
| /** |
| * @private |
| */ |
| private function setValueAt(value:Number, index:int, |
| isProgrammatic:Boolean = false):void |
| { |
| var oldValue:Number = _values[index]; |
| var threshold:Number = (maximum - minimum) / 1000; |
| |
| // we need to do the round of (to remove the floating point error) |
| // if the stepSize had a fractional value |
| if (snapIntervalPrecision != -1) |
| { |
| var scale:Number = Math.pow(10, snapIntervalPrecision); |
| value = Math.round(value * scale) / scale; |
| } |
| |
| _values[index] = value; |
| |
| if (!isProgrammatic) |
| { |
| var event:SliderEvent = new SliderEvent(SliderEvent.CHANGE); |
| event.value = value; |
| event.thumbIndex = index; |
| event.clickTarget = interactionClickTarget; |
| //set the triggerEvent correctly |
| if (keyInteraction) |
| { |
| event.triggerEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN); |
| //reset to mouse default |
| keyInteraction = false; |
| } |
| else |
| { |
| event.triggerEvent = new MouseEvent(MouseEvent.CLICK); |
| } |
| |
| if (!isNaN(oldValue)) |
| { |
| if (Math.abs(oldValue - value) > threshold) |
| dispatchEvent(event) |
| } |
| // Handle case of changing from NaN to a valid value |
| else if (!isNaN(value)) |
| { |
| dispatchEvent(event); |
| } |
| } |
| |
| invalidateDisplayList(); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function registerMouseMove(listener:Function):void |
| { |
| innerSlider.addEventListener(MouseEvent.MOUSE_MOVE, listener); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function unRegisterMouseMove(listener:Function):void |
| { |
| innerSlider.removeEventListener(MouseEvent.MOUSE_MOVE, listener); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Move the thumb when pressed. |
| */ |
| private function track_mouseDownHandler(event:MouseEvent):void |
| { |
| if (event.target != trackHitArea && event.target != ticks) |
| return; |
| if (enabled && allowTrackClick) |
| { |
| interactionClickTarget = SliderEventClickTarget.TRACK; |
| //this is a mouse event |
| keyInteraction = false; |
| var pt:Point = new Point(event.localX, event.localY); |
| var xM:Number = pt.x; |
| var minIndex:Number = 0; |
| var minDistance:Number = 10000000; |
| |
| // find the nearest thumb |
| var n:int = _thumbCount; |
| for (var i:int = 0; i < n; i++) |
| { |
| var d:Number = Math.abs(SliderThumb(thumbs.getChildAt(i)).xPosition - xM); |
| if (d < minDistance) |
| { |
| minIndex = i; |
| minDistance = d; |
| } |
| } |
| var thumb:SliderThumb = SliderThumb(thumbs.getChildAt(minIndex)); |
| if (!isNaN(_snapInterval) && _snapInterval != 0) |
| xM = getXFromValue(getValueFromX(xM)); |
| |
| var duration:Number = getStyle("slideDuration"); |
| var t:Tween = new Tween(thumb, thumb.xPosition, xM, duration); |
| |
| var easingFunction:Function = getStyle("slideEasingFunction") as Function; |
| if (easingFunction != null) |
| t.easingFunction = easingFunction; |
| |
| drawTrackHighlight(); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function thumb_focusInHandler(event:FocusEvent):void |
| { |
| dispatchEvent(event); |
| } |
| |
| /** |
| * @private |
| */ |
| private function thumb_focusOutHandler(event:FocusEvent):void |
| { |
| dispatchEvent(event); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getTrackHitArea():UIComponent |
| { |
| return trackHitArea; |
| } |
| |
| } |
| |
| } |