All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.feathers.controls.Slider.as Maven / Gradle / Ivy

/*
Feathers
Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved.

This program is free software. You can redistribute and/or modify it in
accordance with the terms of the accompanying license agreement.
*/
package feathers.controls
{
	import feathers.core.FeathersControl;
	import feathers.core.IFeathersControl;
	import feathers.core.IFocusDisplayObject;
	import feathers.core.IValidating;
	import feathers.core.PropertyProxy;
	import feathers.events.ExclusiveTouch;
	import feathers.events.FeathersEventType;
	import feathers.layout.Direction;
	import feathers.skins.IStyleProvider;
	import feathers.utils.math.clamp;
	import feathers.utils.math.roundToNearest;

	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	import flash.utils.Timer;

	import starling.display.DisplayObject;
	import starling.events.Event;
	import starling.events.KeyboardEvent;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;

	/**
	 * Dispatched when the slider's value changes.
	 *
	 * 

The properties of the event object have the following values:

* * * * * * *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the * event listener that handles the event. For example, if you use * myButton.addEventListener() to register an event listener, * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; * it is not always the Object listening for the event. Use the * currentTarget property to always access the Object * listening for the event.
* * @eventType starling.events.Event.CHANGE */ [Event(name="change",type="starling.events.Event")] /** * Dispatched when the user starts dragging the slider's thumb or track. * *

The properties of the event object have the following values:

* * * * * * *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the * event listener that handles the event. For example, if you use * myButton.addEventListener() to register an event listener, * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; * it is not always the Object listening for the event. Use the * currentTarget property to always access the Object * listening for the event.
* * @eventType feathers.events.FeathersEventType.BEGIN_INTERACTION */ [Event(name="beginInteraction",type="starling.events.Event")] /** * Dispatched when the user stops dragging the slider's thumb or track. * *

The properties of the event object have the following values:

* * * * * * *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the * event listener that handles the event. For example, if you use * myButton.addEventListener() to register an event listener, * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; * it is not always the Object listening for the event. Use the * currentTarget property to always access the Object * listening for the event.
* * @eventType feathers.events.FeathersEventType.END_INTERACTION */ [Event(name="endInteraction",type="starling.events.Event")] /** * Select a value between a minimum and a maximum by dragging a thumb over * the bounds of a track. The slider's track is divided into two parts split * by the thumb. * *

The following example sets the slider's range and listens for when the * value changes:

* * * var slider:Slider = new Slider(); * slider.minimum = 0; * slider.maximum = 100; * slider.step = 1; * slider.page = 10; * slider.value = 12; * slider.addEventListener( Event.CHANGE, slider_changeHandler ); * this.addChild( slider ); * * @see ../../../help/slider.html How to use the Feathers Slider component */ public class Slider extends FeathersControl implements IDirectionalScrollBar, IFocusDisplayObject { /** * @private */ private static const HELPER_POINT:Point = new Point(); /** * @private */ protected static const INVALIDATION_FLAG_THUMB_FACTORY:String = "thumbFactory"; /** * @private */ protected static const INVALIDATION_FLAG_MINIMUM_TRACK_FACTORY:String = "minimumTrackFactory"; /** * @private */ protected static const INVALIDATION_FLAG_MAXIMUM_TRACK_FACTORY:String = "maximumTrackFactory"; /** * @private * DEPRECATED: Replaced by feathers.layout.Direction.HORIZONTAL. * *

DEPRECATION WARNING: This constant is deprecated * starting with Feathers 3.0. It will be removed in a future version of * Feathers according to the standard * Feathers deprecation policy.

*/ public static const DIRECTION_HORIZONTAL:String = "horizontal"; /** * @private * DEPRECATED: Replaced by feathers.layout.Direction.VERTICAL. * *

DEPRECATION WARNING: This constant is deprecated * starting with Feathers 3.0. It will be removed in a future version of * Feathers according to the standard * Feathers deprecation policy.

*/ public static const DIRECTION_VERTICAL:String = "vertical"; /** * @private * DEPRECATED: Replaced by feathers.controls.TrackLayoutMode.SINGLE. * *

DEPRECATION WARNING: This constant is deprecated * starting with Feathers 3.0. It will be removed in a future version of * Feathers according to the standard * Feathers deprecation policy.

*/ public static const TRACK_LAYOUT_MODE_SINGLE:String = "single"; /** * @private * DEPRECATED: Replaced by feathers.controls.TrackLayoutMode.SPLIT. * *

DEPRECATION WARNING: This constant is deprecated * starting with Feathers 3.0. It will be removed in a future version of * Feathers according to the standard * Feathers deprecation policy.

*/ public static const TRACK_LAYOUT_MODE_MIN_MAX:String = "minMax"; /** * The slider's track dimensions fill the full width and height of the * slider. * * @see #trackScaleMode */ public static const TRACK_SCALE_MODE_EXACT_FIT:String = "exactFit"; /** * If the slider's direction is horizontal, the width of the track will * fill the full width of the slider, and if the slider's direction is * vertical, the height of the track will fill the full height of the * slider. The other edge will not be scaled. * * @see #trackScaleMode */ public static const TRACK_SCALE_MODE_DIRECTIONAL:String = "directional"; /** * When the track is touched, the slider's thumb jumps directly to the * touch position, and the slider's value property is * updated to match as if the thumb were dragged to that position. * * @see #trackInteractionMode */ public static const TRACK_INTERACTION_MODE_TO_VALUE:String = "toValue"; /** * When the track is touched, the slider's thumb jumps directly to the * touch position, and the slider's value property is * updated to match as if the thumb were dragged to that position, and * the thumb may continue to be dragged until the touch ends. * * @see #trackInteractionMode */ public static const TRACK_INTERACTION_MODE_TO_VALUE_WITH_DRAG:String = "toValueWithDrag"; /** * When the track is touched, the value is increased or * decreased (depending on the location of the touch) by the value of * the page property. * * @see #trackInteractionMode */ public static const TRACK_INTERACTION_MODE_BY_PAGE:String = "byPage"; /** * The default value added to the styleNameList of the * minimum track. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_MINIMUM_TRACK:String = "feathers-slider-minimum-track"; /** * The default value added to the styleNameList of the * maximum track. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_MAXIMUM_TRACK:String = "feathers-slider-maximum-track"; /** * The default value added to the styleNameList of the thumb. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_THUMB:String = "feathers-slider-thumb"; /** * The default IStyleProvider for all Slider * components. * * @default null * @see feathers.core.FeathersControl#styleProvider */ public static var globalStyleProvider:IStyleProvider; /** * @private */ protected static function defaultThumbFactory():Button { return new Button(); } /** * @private */ protected static function defaultMinimumTrackFactory():Button { return new Button(); } /** * @private */ protected static function defaultMaximumTrackFactory():Button { return new Button(); } /** * Constructor. */ public function Slider() { super(); this.addEventListener(Event.REMOVED_FROM_STAGE, slider_removedFromStageHandler); } /** * The value added to the styleNameList of the minimum * track. This variable is protected so that sub-classes * can customize the minimum track style name in their constructors * instead of using the default style name defined by * DEFAULT_CHILD_STYLE_NAME_MINIMUM_TRACK. * *

To customize the minimum track style name without subclassing, see * customMinimumTrackStyleName.

* * @see #customMinimumTrackStyleName * @see feathers.core.FeathersControl#styleNameList */ protected var minimumTrackStyleName:String = DEFAULT_CHILD_STYLE_NAME_MINIMUM_TRACK; /** * The value added to the styleNameList of the maximum * track. This variable is protected so that sub-classes * can customize the maximum track style name in their constructors * instead of using the default style name defined by * DEFAULT_CHILD_STYLE_NAME_MAXIMUM_TRACK. * *

To customize the maximum track style name without subclassing, see * customMaximumTrackStyleName.

* * @see #customMaximumTrackStyleName * @see feathers.core.FeathersControl#styleNameList */ protected var maximumTrackStyleName:String = DEFAULT_CHILD_STYLE_NAME_MAXIMUM_TRACK; /** * The value added to the styleNameList of the thumb. This * variable is protected so that sub-classes can customize * the thumb style name in their constructors instead of using the * default style name defined by DEFAULT_CHILD_STYLE_NAME_THUMB. * *

To customize the thumb style name without subclassing, see * customThumbStyleName.

* * @see #customThumbStyleName * @see feathers.core.FeathersControl#styleNameList */ protected var thumbStyleName:String = DEFAULT_CHILD_STYLE_NAME_THUMB; /** * The thumb sub-component. * *

For internal use in subclasses.

* * @see #thumbFactory * @see #createThumb() */ protected var thumb:DisplayObject; /** * The minimum track sub-component. * *

For internal use in subclasses.

* * @see #minimumTrackFactory * @see #createMinimumTrack() */ protected var minimumTrack:DisplayObject; /** * The maximum track sub-component. * *

For internal use in subclasses.

* * @see #maximumTrackFactory * @see #createMaximumTrack() */ protected var maximumTrack:DisplayObject; /** * @private */ protected var minimumTrackOriginalWidth:Number = NaN; /** * @private */ protected var minimumTrackOriginalHeight:Number = NaN; /** * @private */ protected var maximumTrackOriginalWidth:Number = NaN; /** * @private */ protected var maximumTrackOriginalHeight:Number = NaN; /** * @private */ override protected function get defaultStyleProvider():IStyleProvider { return Slider.globalStyleProvider; } /** * @private */ protected var _direction:String = Direction.HORIZONTAL; [Inspectable(type="String",enumeration="horizontal,vertical")] /** * Determines if the slider's thumb can be dragged horizontally or * vertically. When this value changes, the slider's width and height * values do not change automatically. * *

In the following example, the direction is changed to vertical:

* * * slider.direction = Direction.VERTICAL; * * @default feathers.layout.Direction.HORIZONTAL * * @see feathers.layout.Direction#HORIZONTAL * @see feathers.layout.Direction#VERTICAL */ public function get direction():String { return this._direction; } /** * @private */ public function set direction(value:String):void { if(this._direction == value) { return; } this._direction = value; this.invalidate(INVALIDATION_FLAG_DATA); this.invalidate(INVALIDATION_FLAG_MINIMUM_TRACK_FACTORY); this.invalidate(INVALIDATION_FLAG_MAXIMUM_TRACK_FACTORY); this.invalidate(INVALIDATION_FLAG_THUMB_FACTORY); } /** * @private */ protected var _value:Number = 0; /** * The value of the slider, between the minimum and maximum. * *

In the following example, the value is changed to 12:

* * * slider.minimum = 0; * slider.maximum = 100; * slider.step = 1; * slider.page = 10 * slider.value = 12; * * @default 0 * * @see #minimum * @see #maximum * @see #step * @see #page */ public function get value():Number { return this._value; } /** * @private */ public function set value(newValue:Number):void { if(this._step != 0 && newValue != this._maximum && newValue != this._minimum) { newValue = roundToNearest(newValue - this._minimum, this._step) + this._minimum; } newValue = clamp(newValue, this._minimum, this._maximum); if(this._value == newValue) { return; } this._value = newValue; this.invalidate(INVALIDATION_FLAG_DATA); if(this.liveDragging || !this.isDragging) { this.dispatchEventWith(Event.CHANGE); } } /** * @private */ protected var _minimum:Number = 0; /** * The slider's value will not go lower than the minimum. * *

In the following example, the minimum is set to 0:

* * * slider.minimum = 0; * slider.maximum = 100; * slider.step = 1; * slider.page = 10 * slider.value = 12; * * @default 0 * * @see #value * @see #maximum */ public function get minimum():Number { return this._minimum; } /** * @private */ public function set minimum(value:Number):void { if(this._minimum == value) { return; } this._minimum = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _maximum:Number = 0; /** * The slider's value will not go higher than the maximum. The maximum * is zero (0), by default, and it should almost always be * changed to something more appropriate. * *

In the following example, the maximum is set to 100:

* * * slider.minimum = 0; * slider.maximum = 100; * slider.step = 1; * slider.page = 10 * slider.value = 12; * * @default 0 * * @see #value * @see #minimum */ public function get maximum():Number { return this._maximum; } /** * @private */ public function set maximum(value:Number):void { if(this._maximum == value) { return; } this._maximum = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _step:Number = 0; /** * As the slider's thumb is dragged, the value is snapped to a multiple * of the step. Paging using the slider's track will use the step * value if the page value is NaN. If the * step is zero (0), paging with the track will not be possible. * *

In the following example, the step is changed to 1:

* * * slider.minimum = 0; * slider.maximum = 100; * slider.step = 1; * slider.page = 10; * slider.value = 10; * * @default 0 * * @see #value * @see #page */ public function get step():Number { return this._step; } /** * @private */ public function set step(value:Number):void { if(this._step == value) { return; } this._step = value; } /** * @private */ protected var _page:Number = NaN; /** * If the trackInteractionMode property is set to * Slider.TRACK_INTERACTION_MODE_BY_PAGE, and the slider's * track is touched, and the thumb is shown, the slider value will be * incremented or decremented by the page value. * *

If this value is NaN, the step value * will be used instead. If the step value is zero, paging * with the track is not possible.

* *

In the following example, the page is changed to 10:

* * * slider.minimum = 0; * slider.maximum = 100; * slider.step = 1; * slider.page = 10 * slider.value = 12; * * @default NaN * * @see #value * @see #page * @see #trackInteractionMode */ public function get page():Number { return this._page; } /** * @private */ public function set page(value:Number):void { if(this._page == value) { return; } this._page = value; } /** * @private */ protected var isDragging:Boolean = false; /** * Determines if the slider dispatches the Event.CHANGE * event every time the thumb moves, or only once it stops moving. * *

In the following example, live dragging is disabled:

* * * slider.liveDragging = false; * * @default true */ public var liveDragging:Boolean = true; /** * @private */ protected var _showThumb:Boolean = true; /** * Determines if the thumb should be displayed. * *

In the following example, the thumb is hidden:

* * * slider.showThumb = false; * * @default true */ public function get showThumb():Boolean { return this._showThumb; } /** * @private */ public function set showThumb(value:Boolean):void { if(this._showThumb == value) { return; } this._showThumb = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _thumbOffset:Number = 0; /** * * Offsets the position of the thumb by a certain number of pixels in a * direction perpendicular to the track. This does not affect the * measurement of the slider. The slider will measure itself as if the * thumb were not offset from its original position. * *

In the following example, the thumb is offset by 20 pixels:

* * * slider.thumbOffset = 20; * * @default 0 */ public function get thumbOffset():Number { return this._thumbOffset; } /** * @private */ public function set thumbOffset(value:Number):void { if(this._thumbOffset == value) { return; } this._thumbOffset = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _minimumPadding:Number = 0; /** * The space, in pixels, between the minimum position of the thumb and * the minimum edge of the track. May be negative to extend the range of * the thumb. * *

In the following example, minimum padding is set to 20 pixels:

* * * slider.minimumPadding = 20; * * @default 0 */ public function get minimumPadding():Number { return this._minimumPadding; } /** * @private */ public function set minimumPadding(value:Number):void { if(this._minimumPadding == value) { return; } this._minimumPadding = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _maximumPadding:Number = 0; /** * The space, in pixels, between the maximum position of the thumb and * the maximum edge of the track. May be negative to extend the range * of the thumb. * *

In the following example, maximum padding is set to 20 pixels:

* * * slider.maximumPadding = 20; * * @default 0 */ public function get maximumPadding():Number { return this._maximumPadding; } /** * @private */ public function set maximumPadding(value:Number):void { if(this._maximumPadding == value) { return; } this._maximumPadding = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _trackLayoutMode:String = TrackLayoutMode.SINGLE; [Inspectable(type="String",enumeration="single,split")] /** * Determines how the minimum and maximum track skins are positioned and * sized. * *

In the following example, the slider is given two tracks:

* * * slider.trackLayoutMode = TrackLayoutMode.SPLIT; * * @default feathers.controls.TrackLayoutMode.SINGLE * * @see feathers.controls.TrackLayoutMode#SINGLE * @see feathers.controls.TrackLayoutMode#SPLIT */ public function get trackLayoutMode():String { return this._trackLayoutMode; } /** * @private */ public function set trackLayoutMode(value:String):void { if(value === TRACK_LAYOUT_MODE_MIN_MAX) { value = TrackLayoutMode.SPLIT; } if(this._trackLayoutMode == value) { return; } this._trackLayoutMode = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _trackScaleMode:String = TRACK_SCALE_MODE_DIRECTIONAL; [Inspectable(type="String",enumeration="exactFit,directional")] /** * Determines how the minimum and maximum track skins are positioned and * sized. * *

In the following example, the slider's track layout is customized:

* * * slider.trackScaleMode = Slider.TRACK_SCALE_MODE_EXACT_FIT; * * @default Slider.TRACK_SCALE_MODE_DIRECTIONAL * * @see #TRACK_SCALE_MODE_DIRECTIONAL * @see #TRACK_SCALE_MODE_EXACT_FIT * @see #trackLayoutMode */ public function get trackScaleMode():String { return this._trackScaleMode; } /** * @private */ public function set trackScaleMode(value:String):void { if(this._trackScaleMode == value) { return; } this._trackScaleMode = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _trackInteractionMode:String = TRACK_INTERACTION_MODE_TO_VALUE; [Inspectable(type="String",enumeration="toValue,toValueWithDrag,byPage")] /** * Determines how the slider's value changes when the track is touched. * *

If showThumb is set to false, the slider * will always behave as if trackInteractionMode has been * set to Slider.TRACK_INTERACTION_MODE_TO_VALUE. In other * words, the value of trackInteractionMode may be ignored * if the thumb is hidden.

* *

In the following example, the slider's track interaction is changed:

* * * slider.trackScaleMode = Slider.TRACK_INTERACTION_MODE_BY_PAGE; * * @default Slider.TRACK_INTERACTION_MODE_TO_VALUE * * @see #TRACK_INTERACTION_MODE_TO_VALUE * @see #TRACK_INTERACTION_MODE_TO_VALUE_WITH_DRAG * @see #TRACK_INTERACTION_MODE_BY_PAGE * @see #page */ public function get trackInteractionMode():String { return this._trackInteractionMode; } /** * @private */ public function set trackInteractionMode(value:String):void { this._trackInteractionMode = value; } /** * @private */ protected var currentRepeatAction:Function; /** * @private */ protected var _repeatTimer:Timer; /** * @private */ protected var _repeatDelay:Number = 0.05; /** * The time, in seconds, before actions are repeated. The first repeat * happens after a delay that is five times longer than the following * repeats. * *

In the following example, the slider's repeat delay is set to * 500 milliseconds:

* * * slider.repeatDelay = 0.5; * * @default 0.05 */ public function get repeatDelay():Number { return this._repeatDelay; } /** * @private */ public function set repeatDelay(value:Number):void { if(this._repeatDelay == value) { return; } this._repeatDelay = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _minimumTrackFactory:Function; /** * A function used to generate the slider's minimum track sub-component. * The minimum track must be an instance of Button. This * factory can be used to change properties on the minimum track when it * is first created. For instance, if you are skinning Feathers * components without a theme, you might use this factory to set skins * and other styles on the minimum track. * *

The function should have the following signature:

*
function():Button
* *

In the following example, a custom minimum track factory is passed * to the slider:

* * * slider.minimumTrackFactory = function():Button * { * var track:Button = new Button(); * track.defaultSkin = new Image( upTexture ); * track.downSkin = new Image( downTexture ); * return track; * }; * * @default null * * @see feathers.controls.Button * @see #minimumTrackProperties */ public function get minimumTrackFactory():Function { return this._minimumTrackFactory; } /** * @private */ public function set minimumTrackFactory(value:Function):void { if(this._minimumTrackFactory == value) { return; } this._minimumTrackFactory = value; this.invalidate(INVALIDATION_FLAG_MINIMUM_TRACK_FACTORY); } /** * @private */ protected var _customMinimumTrackStyleName:String; /** * A style name to add to the slider's minimum track sub-component. * Typically used by a theme to provide different styles to different * sliders. * *

In the following example, a custom minimum track style name is * passed to the slider:

* * * slider.customMinimumTrackStyleName = "my-custom-minimum-track"; * *

In your theme, you can target this sub-component style name to * provide different styles than the default:

* * * getStyleProviderForClass( Button ).setFunctionForStyleName( "my-custom-minimum-track", setCustomMinimumTrackStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_MINIMUM_TRACK * @see feathers.core.FeathersControl#styleNameList * @see #minimumTrackFactory * @see #minimumTrackProperties */ public function get customMinimumTrackStyleName():String { return this._customMinimumTrackStyleName; } /** * @private */ public function set customMinimumTrackStyleName(value:String):void { if(this._customMinimumTrackStyleName == value) { return; } this._customMinimumTrackStyleName = value; this.invalidate(INVALIDATION_FLAG_MINIMUM_TRACK_FACTORY); } /** * @private */ protected var _minimumTrackProperties:PropertyProxy; /** * An object that stores properties for the slider's "minimum" track, * and the properties will be passed down to the "minimum" track when * the slider validates. For a list of available properties, refer to * feathers.controls.Button. * *

If the subcomponent has its own subcomponents, their properties * can be set too, using attribute @ notation. For example, * to set the skin on the thumb which is in a SimpleScrollBar, * which is in a List, you can use the following syntax:

*
list.verticalScrollBarProperties.@thumbProperties.defaultSkin = new Image(texture);
* *

Setting properties in a minimumTrackFactory function * instead of using minimumTrackProperties will result in * better performance.

* *

In the following example, the slider's minimum track properties * are updated:

* * * slider.minimumTrackProperties.defaultSkin = new Image( upTexture ); * slider.minimumTrackProperties.downSkin = new Image( downTexture ); * * @default null * * @see #minimumTrackFactory * @see feathers.controls.Button */ public function get minimumTrackProperties():Object { if(!this._minimumTrackProperties) { this._minimumTrackProperties = new PropertyProxy(childProperties_onChange); } return this._minimumTrackProperties; } /** * @private */ public function set minimumTrackProperties(value:Object):void { if(this._minimumTrackProperties == value) { return; } if(!value) { value = new PropertyProxy(); } if(!(value is PropertyProxy)) { var newValue:PropertyProxy = new PropertyProxy(); for(var propertyName:String in value) { newValue[propertyName] = value[propertyName]; } value = newValue; } if(this._minimumTrackProperties) { this._minimumTrackProperties.removeOnChangeCallback(childProperties_onChange); } this._minimumTrackProperties = PropertyProxy(value); if(this._minimumTrackProperties) { this._minimumTrackProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _maximumTrackFactory:Function; /** * A function used to generate the slider's maximum track sub-component. * The maximum track must be an instance of Button. * This factory can be used to change properties on the maximum track * when it is first created. For instance, if you are skinning Feathers * components without a theme, you might use this factory to set skins * and other styles on the maximum track. * *

The function should have the following signature:

*
function():Button
* *

In the following example, a custom maximum track factory is passed * to the slider:

* * * slider.maximumTrackFactory = function():Button * { * var track:Button = new Button(); * track.defaultSkin = new Image( upTexture ); * track.downSkin = new Image( downTexture ); * return track; * }; * * @default null * * @see feathers.controls.Button * @see #maximumTrackProperties */ public function get maximumTrackFactory():Function { return this._maximumTrackFactory; } /** * @private */ public function set maximumTrackFactory(value:Function):void { if(this._maximumTrackFactory == value) { return; } this._maximumTrackFactory = value; this.invalidate(INVALIDATION_FLAG_MAXIMUM_TRACK_FACTORY); } /** * @private */ protected var _customMaximumTrackStyleName:String; /** * A style name to add to the slider's maximum track sub-component. * Typically used by a theme to provide different skins to different * sliders. * *

In the following example, a custom maximum track style name is * passed to the slider:

* * * slider.customMaximumTrackStyleName = "my-custom-maximum-track"; * *

In your theme, you can target this sub-component style name to * provide different styles than the default:

* * * getStyleProviderForClass( Button ).setFunctionForStyleName( "my-custom-maximum-track", setCustomMaximumTrackStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_MAXIMUM_TRACK * @see feathers.core.FeathersControl#styleNameList * @see #maximumTrackFactory * @see #maximumTrackProperties */ public function get customMaximumTrackStyleName():String { return this._customMaximumTrackStyleName; } /** * @private */ public function set customMaximumTrackStyleName(value:String):void { if(this._customMaximumTrackStyleName == value) { return; } this._customMaximumTrackStyleName = value; this.invalidate(INVALIDATION_FLAG_MAXIMUM_TRACK_FACTORY); } /** * @private */ protected var _maximumTrackProperties:PropertyProxy; /** * An object that stores properties for the slider's "maximum" track, * and the properties will be passed down to the "maximum" track when * the slider validates. For a list of available properties, refer to * feathers.controls.Button. * *

If the subcomponent has its own subcomponents, their properties * can be set too, using attribute @ notation. For example, * to set the skin on the thumb which is in a SimpleScrollBar, * which is in a List, you can use the following syntax:

*
list.verticalScrollBarProperties.@thumbProperties.defaultSkin = new Image(texture);
* *

Setting properties in a maximumTrackFactory function * instead of using maximumTrackProperties will result in * better performance.

* *

In the following example, the slider's maximum track properties * are updated:

* * * slider.maximumTrackProperties.defaultSkin = new Image( upTexture ); * slider.maximumTrackProperties.downSkin = new Image( downTexture ); * * @default null * * @see #maximumTrackFactory * @see feathers.controls.Button */ public function get maximumTrackProperties():Object { if(!this._maximumTrackProperties) { this._maximumTrackProperties = new PropertyProxy(childProperties_onChange); } return this._maximumTrackProperties; } /** * @private */ public function set maximumTrackProperties(value:Object):void { if(this._maximumTrackProperties == value) { return; } if(!value) { value = new PropertyProxy(); } if(!(value is PropertyProxy)) { var newValue:PropertyProxy = new PropertyProxy(); for(var propertyName:String in value) { newValue[propertyName] = value[propertyName]; } value = newValue; } if(this._maximumTrackProperties) { this._maximumTrackProperties.removeOnChangeCallback(childProperties_onChange); } this._maximumTrackProperties = PropertyProxy(value); if(this._maximumTrackProperties) { this._maximumTrackProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _thumbFactory:Function; /** * A function used to generate the slider's thumb sub-component. * The thumb must be an instance of Button. This factory * can be used to change properties on the thumb when it is first * created. For instance, if you are skinning Feathers components * without a theme, you might use this factory to set skins and other * styles on the thumb. * *

The function should have the following signature:

*
function():Button
* *

In the following example, a custom thumb factory is passed * to the slider:

* * * slider.thumbFactory = function():Button * { * var thumb:Button = new Button(); * thumb.defaultSkin = new Image( upTexture ); * thumb.downSkin = new Image( downTexture ); * return thumb; * }; * * @default null * * @see feathers.controls.Button * @see #thumbProperties */ public function get thumbFactory():Function { return this._thumbFactory; } /** * @private */ public function set thumbFactory(value:Function):void { if(this._thumbFactory == value) { return; } this._thumbFactory = value; this.invalidate(INVALIDATION_FLAG_THUMB_FACTORY); } /** * @private */ protected var _customThumbStyleName:String; /** * A style name to add to the slider's thumb sub-component. Typically * used by a theme to provide different styles to different sliders. * *

In the following example, a custom thumb style name is passed * to the slider:

* * * slider.customThumbStyleName = "my-custom-thumb"; * *

In your theme, you can target this sub-component style name to * provide different styles than the default:

* * * getStyleProviderForClass( Button ).setFunctionForStyleName( "my-custom-thumb", setCustomThumbStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_THUMB * @see feathers.core.FeathersControl#styleNameList * @see #thumbFactory * @see #thumbProperties */ public function get customThumbStyleName():String { return this._customThumbStyleName; } /** * @private */ public function set customThumbStyleName(value:String):void { if(this._customThumbStyleName == value) { return; } this._customThumbStyleName = value; this.invalidate(INVALIDATION_FLAG_THUMB_FACTORY); } /** * @private */ protected var _thumbProperties:PropertyProxy; /** * An object that stores properties for the slider's thumb, and the * properties will be passed down to the thumb when the slider * validates. For a list of available properties, refer to * feathers.controls.Button. * *

If the subcomponent has its own subcomponents, their properties * can be set too, using attribute @ notation. For example, * to set the skin on the thumb which is in a SimpleScrollBar, * which is in a List, you can use the following syntax:

*
list.verticalScrollBarProperties.@thumbProperties.defaultSkin = new Image(texture);
* *

Setting properties in a thumbFactory function instead * of using thumbProperties will result in better * performance.

* *

In the following example, the slider's thumb properties * are updated:

* * * slider.thumbProperties.defaultSkin = new Image( upTexture ); * slider.thumbProperties.downSkin = new Image( downTexture ); * * @default null * * @see feathers.controls.Button * @see #thumbFactory */ public function get thumbProperties():Object { if(!this._thumbProperties) { this._thumbProperties = new PropertyProxy(childProperties_onChange); } return this._thumbProperties; } /** * @private */ public function set thumbProperties(value:Object):void { if(this._thumbProperties == value) { return; } if(!value) { value = new PropertyProxy(); } if(!(value is PropertyProxy)) { var newValue:PropertyProxy = new PropertyProxy(); for(var propertyName:String in value) { newValue[propertyName] = value[propertyName]; } value = newValue; } if(this._thumbProperties) { this._thumbProperties.removeOnChangeCallback(childProperties_onChange); } this._thumbProperties = PropertyProxy(value); if(this._thumbProperties) { this._thumbProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _touchPointID:int = -1; /** * @private */ protected var _touchStartX:Number = NaN; /** * @private */ protected var _touchStartY:Number = NaN; /** * @private */ protected var _thumbStartX:Number = NaN; /** * @private */ protected var _thumbStartY:Number = NaN; /** * @private */ protected var _touchValue:Number; /** * @private */ override protected function initialize():void { if(this._value < this._minimum) { this.value = this._minimum; } else if(this._value > this._maximum) { this.value = this._maximum; } } /** * @private */ override protected function draw():void { var stylesInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STYLES); var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE); var stateInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_STATE); var focusInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_FOCUS); var layoutInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_LAYOUT); var thumbFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_THUMB_FACTORY); var minimumTrackFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_MINIMUM_TRACK_FACTORY); var maximumTrackFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_MAXIMUM_TRACK_FACTORY); if(thumbFactoryInvalid) { this.createThumb(); } if(minimumTrackFactoryInvalid) { this.createMinimumTrack(); } if(maximumTrackFactoryInvalid || layoutInvalid) { this.createMaximumTrack(); } if(thumbFactoryInvalid || stylesInvalid) { this.refreshThumbStyles(); } if(minimumTrackFactoryInvalid || stylesInvalid) { this.refreshMinimumTrackStyles(); } if((maximumTrackFactoryInvalid || layoutInvalid || stylesInvalid) && this.maximumTrack) { this.refreshMaximumTrackStyles(); } if(stateInvalid || thumbFactoryInvalid || minimumTrackFactoryInvalid || maximumTrackFactoryInvalid) { this.refreshEnabled(); } sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid; this.layoutChildren(); if(sizeInvalid || focusInvalid) { this.refreshFocusIndicator(); } } /** * If the component's dimensions have not been set explicitly, it will * measure its content and determine an ideal size for itself. If the * explicitWidth or explicitHeight member * variables are set, those value will be used without additional * measurement. If one is set, but not the other, the dimension with the * explicit value will not be measured, but the other non-explicit * dimension will still need measurement. * *

Calls setSizeInternal() to set up the * actualWidth and actualHeight member * variables used for layout.

* *

Meant for internal use, and subclasses may override this function * with a custom implementation.

*/ protected function autoSizeIfNeeded():Boolean { if(this.minimumTrackOriginalWidth !== this.minimumTrackOriginalWidth || //isNaN this.minimumTrackOriginalHeight !== this.minimumTrackOriginalHeight) //isNaN { if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } this.minimumTrackOriginalWidth = this.minimumTrack.width; this.minimumTrackOriginalHeight = this.minimumTrack.height; } if(this.maximumTrack) { if(this.maximumTrackOriginalWidth !== this.maximumTrackOriginalWidth || //isNaN this.maximumTrackOriginalHeight !== this.maximumTrackOriginalHeight) //isNaN { if(this.maximumTrack is IValidating) { IValidating(this.maximumTrack).validate(); } this.maximumTrackOriginalWidth = this.maximumTrack.width; this.maximumTrackOriginalHeight = this.maximumTrack.height; } } var needsWidth:Boolean = this._explicitWidth !== this._explicitWidth; //isNaN var needsHeight:Boolean = this._explicitHeight !== this._explicitHeight; //isNaN if(!needsWidth && !needsHeight) { return false; } if(this.thumb is IValidating) { IValidating(this.thumb).validate(); } var newWidth:Number = this._explicitWidth; var newHeight:Number = this._explicitHeight; if(needsWidth) { if(this._direction == Direction.VERTICAL) { if(this.maximumTrack) { newWidth = Math.max(this.minimumTrackOriginalWidth, this.maximumTrackOriginalWidth); } else { newWidth = this.minimumTrackOriginalWidth; } } else //horizontal { if(this.maximumTrack) { newWidth = Math.min(this.minimumTrackOriginalWidth, this.maximumTrackOriginalWidth) + this.thumb.width / 2; } else { newWidth = this.minimumTrackOriginalWidth; } } newWidth = Math.max(newWidth, this.thumb.width); } if(needsHeight) { if(this._direction == Direction.VERTICAL) { if(this.maximumTrack) { newHeight = Math.min(this.minimumTrackOriginalHeight, this.maximumTrackOriginalHeight) + this.thumb.height / 2; } else { newHeight = this.minimumTrackOriginalHeight; } } else //horizontal { if(this.maximumTrack) { newHeight = Math.max(this.minimumTrackOriginalHeight, this.maximumTrackOriginalHeight); } else { newHeight = this.minimumTrackOriginalHeight; } } newHeight = Math.max(newHeight, this.thumb.height); } return this.setSizeInternal(newWidth, newHeight, false); } /** * Creates and adds the thumb sub-component and * removes the old instance, if one exists. * *

Meant for internal use, and subclasses may override this function * with a custom implementation.

* * @see #thumb * @see #thumbFactory * @see #customThumbStyleName */ protected function createThumb():void { if(this.thumb) { this.thumb.removeFromParent(true); this.thumb = null; } var factory:Function = this._thumbFactory != null ? this._thumbFactory : defaultThumbFactory; var thumbStyleName:String = this._customThumbStyleName != null ? this._customThumbStyleName : this.thumbStyleName; var thumb:Button = Button(factory()); thumb.styleNameList.add(thumbStyleName); thumb.keepDownStateOnRollOut = true; thumb.addEventListener(TouchEvent.TOUCH, thumb_touchHandler); this.addChild(thumb); this.thumb = thumb; } /** * Creates and adds the minimumTrack sub-component and * removes the old instance, if one exists. * *

Meant for internal use, and subclasses may override this function * with a custom implementation.

* * @see #minimumTrack * @see #minimumTrackFactory * @see #customMinimumTrackStyleName */ protected function createMinimumTrack():void { if(this.minimumTrack) { this.minimumTrack.removeFromParent(true); this.minimumTrack = null; } var factory:Function = this._minimumTrackFactory != null ? this._minimumTrackFactory : defaultMinimumTrackFactory; var minimumTrackStyleName:String = this._customMinimumTrackStyleName != null ? this._customMinimumTrackStyleName : this.minimumTrackStyleName; var minimumTrack:Button = Button(factory()); minimumTrack.styleNameList.add(minimumTrackStyleName); minimumTrack.keepDownStateOnRollOut = true; minimumTrack.addEventListener(TouchEvent.TOUCH, track_touchHandler); this.addChildAt(minimumTrack, 0); this.minimumTrack = minimumTrack; } /** * Creates and adds the maximumTrack sub-component and * removes the old instance, if one exists. If the maximum track is not * needed, it will not be created. * *

Meant for internal use, and subclasses may override this function * with a custom implementation.

* * @see #maximumTrack * @see #maximumTrackFactory * @see #customMaximumTrackStyleName */ protected function createMaximumTrack():void { if(this._trackLayoutMode == TrackLayoutMode.SPLIT) { if(this.maximumTrack) { this.maximumTrack.removeFromParent(true); this.maximumTrack = null; } var factory:Function = this._maximumTrackFactory != null ? this._maximumTrackFactory : defaultMaximumTrackFactory; var maximumTrackStyleName:String = this._customMaximumTrackStyleName != null ? this._customMaximumTrackStyleName : this.maximumTrackStyleName; var maximumTrack:Button = Button(factory()); maximumTrack.styleNameList.add(maximumTrackStyleName); maximumTrack.keepDownStateOnRollOut = true; maximumTrack.addEventListener(TouchEvent.TOUCH, track_touchHandler); this.addChildAt(maximumTrack, 1); this.maximumTrack = maximumTrack; } else if(this.maximumTrack) //single { this.maximumTrack.removeFromParent(true); this.maximumTrack = null; } } /** * @private */ protected function refreshThumbStyles():void { for(var propertyName:String in this._thumbProperties) { var propertyValue:Object = this._thumbProperties[propertyName]; this.thumb[propertyName] = propertyValue; } this.thumb.visible = this._showThumb; } /** * @private */ protected function refreshMinimumTrackStyles():void { for(var propertyName:String in this._minimumTrackProperties) { var propertyValue:Object = this._minimumTrackProperties[propertyName]; this.minimumTrack[propertyName] = propertyValue; } } /** * @private */ protected function refreshMaximumTrackStyles():void { if(!this.maximumTrack) { return; } for(var propertyName:String in this._maximumTrackProperties) { var propertyValue:Object = this._maximumTrackProperties[propertyName]; this.maximumTrack[propertyName] = propertyValue; } } /** * @private */ protected function refreshEnabled():void { if(this.thumb is IFeathersControl) { IFeathersControl(this.thumb).isEnabled = this._isEnabled; } if(this.minimumTrack is IFeathersControl) { IFeathersControl(this.minimumTrack).isEnabled = this._isEnabled; } if(this.maximumTrack is IFeathersControl) { IFeathersControl(this.maximumTrack).isEnabled = this._isEnabled; } } /** * @private */ protected function layoutChildren():void { this.layoutThumb(); if(this._trackLayoutMode == TrackLayoutMode.SPLIT) { this.layoutTrackWithMinMax(); } else //single { this.layoutTrackWithSingle(); } } /** * @private */ protected function layoutThumb():void { //this will auto-size the thumb, if needed if(this.thumb is IValidating) { IValidating(this.thumb).validate(); } if(this._minimum === this._maximum) { var percentage:Number = 1; } else { percentage = (this._value - this._minimum) / (this._maximum - this._minimum); if(percentage < 0) { percentage = 0; } else if(percentage > 1) { percentage = 1; } } if(this._direction == Direction.VERTICAL) { var trackScrollableHeight:Number = this.actualHeight - this.thumb.height - this._minimumPadding - this._maximumPadding; this.thumb.x = Math.round((this.actualWidth - this.thumb.width) / 2) + this._thumbOffset; //maximum is at the top, so we need to start the y position of //the thumb from the maximum padding this.thumb.y = Math.round(this._maximumPadding + trackScrollableHeight * (1 - percentage)); } else //horizontal { var trackScrollableWidth:Number = this.actualWidth - this.thumb.width - this._minimumPadding - this._maximumPadding; //minimum is at the left, so we need to start the x position of //the thumb from the minimum padding this.thumb.x = Math.round(this._minimumPadding + (trackScrollableWidth * percentage)); this.thumb.y = Math.round((this.actualHeight - this.thumb.height) / 2) + this._thumbOffset; } } /** * @private */ protected function layoutTrackWithMinMax():void { if(this._direction == Direction.VERTICAL) { this.maximumTrack.y = 0; this.maximumTrack.height = this.thumb.y + this.thumb.height / 2; this.minimumTrack.y = this.maximumTrack.height; this.minimumTrack.height = this.actualHeight - this.minimumTrack.y; if(this._trackScaleMode == TRACK_SCALE_MODE_DIRECTIONAL) { this.maximumTrack.width = NaN; if(this.maximumTrack is IValidating) { IValidating(this.maximumTrack).validate(); } this.maximumTrack.x = (this.actualWidth - this.maximumTrack.width) / 2; this.minimumTrack.width = NaN; if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } this.minimumTrack.x = (this.actualWidth - this.minimumTrack.width) / 2; } else //exact fit { this.maximumTrack.x = 0; this.maximumTrack.width = this.actualWidth; this.minimumTrack.x = 0; this.minimumTrack.width = this.actualWidth; //final validation to avoid juggler next frame issues if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } if(this.maximumTrack is IValidating) { IValidating(this.maximumTrack).validate(); } } } else //horizontal { this.minimumTrack.x = 0; this.minimumTrack.width = this.thumb.x + this.thumb.width / 2; this.maximumTrack.x = this.minimumTrack.width; this.maximumTrack.width = this.actualWidth - this.maximumTrack.x; if(this._trackScaleMode == TRACK_SCALE_MODE_DIRECTIONAL) { this.minimumTrack.height = NaN; if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } this.minimumTrack.y = (this.actualHeight - this.minimumTrack.height) / 2; this.maximumTrack.height = NaN; if(this.maximumTrack is IValidating) { IValidating(this.maximumTrack).validate(); } this.maximumTrack.y = (this.actualHeight - this.maximumTrack.height) / 2; } else //exact fit { this.minimumTrack.y = 0; this.minimumTrack.height = this.actualHeight; this.maximumTrack.y = 0; this.maximumTrack.height = this.actualHeight; //final validation to avoid juggler next frame issues if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } if(this.maximumTrack is IValidating) { IValidating(this.maximumTrack).validate(); } } } } /** * @private */ protected function layoutTrackWithSingle():void { if(this._trackScaleMode == TRACK_SCALE_MODE_DIRECTIONAL) { if(this._direction == Direction.VERTICAL) { this.minimumTrack.y = 0; this.minimumTrack.width = NaN; this.minimumTrack.height = this.actualHeight; if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } this.minimumTrack.x = (this.actualWidth - this.minimumTrack.width) / 2; } else //horizontal { this.minimumTrack.x = 0; this.minimumTrack.width = this.actualWidth; this.minimumTrack.height = NaN; if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } this.minimumTrack.y = (this.actualHeight - this.minimumTrack.height) / 2; } } else //exact fit { this.minimumTrack.x = 0; this.minimumTrack.y = 0; this.minimumTrack.width = this.actualWidth; this.minimumTrack.height = this.actualHeight; //final validation to avoid juggler next frame issues if(this.minimumTrack is IValidating) { IValidating(this.minimumTrack).validate(); } } } /** * @private */ protected function locationToValue(location:Point):Number { var percentage:Number; if(this._direction == Direction.VERTICAL) { var trackScrollableHeight:Number = this.actualHeight - this.thumb.height - this._minimumPadding - this._maximumPadding; var yOffset:Number = location.y - this._touchStartY - this._maximumPadding; var yPosition:Number = Math.min(Math.max(0, this._thumbStartY + yOffset), trackScrollableHeight); percentage = 1 - (yPosition / trackScrollableHeight); } else //horizontal { var trackScrollableWidth:Number = this.actualWidth - this.thumb.width - this._minimumPadding - this._maximumPadding; var xOffset:Number = location.x - this._touchStartX - this._minimumPadding; var xPosition:Number = Math.min(Math.max(0, this._thumbStartX + xOffset), trackScrollableWidth); percentage = xPosition / trackScrollableWidth; } return this._minimum + percentage * (this._maximum - this._minimum); } /** * @private */ protected function startRepeatTimer(action:Function):void { this.currentRepeatAction = action; if(this._repeatDelay > 0) { if(!this._repeatTimer) { this._repeatTimer = new Timer(this._repeatDelay * 1000); this._repeatTimer.addEventListener(TimerEvent.TIMER, repeatTimer_timerHandler); } else { this._repeatTimer.reset(); this._repeatTimer.delay = this._repeatDelay * 1000; } this._repeatTimer.start(); } } /** * @private */ protected function adjustPage():void { var page:Number = this._page; if(page !== page) //isNaN { page = this._step; } if(this._touchValue < this._value) { this.value = Math.max(this._touchValue, this._value - page); } else if(this._touchValue > this._value) { this.value = Math.min(this._touchValue, this._value + page); } } /** * @private */ protected function childProperties_onChange(proxy:PropertyProxy, name:Object):void { this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected function slider_removedFromStageHandler(event:Event):void { this._touchPointID = -1; var wasDragging:Boolean = this.isDragging; this.isDragging = false; if(wasDragging && !this.liveDragging) { this.dispatchEventWith(Event.CHANGE); } } /** * @private */ override protected function focusInHandler(event:Event):void { super.focusInHandler(event); this.stage.addEventListener(KeyboardEvent.KEY_DOWN, stage_keyDownHandler); } /** * @private */ override protected function focusOutHandler(event:Event):void { super.focusOutHandler(event); this.stage.removeEventListener(KeyboardEvent.KEY_DOWN, stage_keyDownHandler); } /** * @private */ protected function track_touchHandler(event:TouchEvent):void { if(!this._isEnabled) { this._touchPointID = -1; return; } var track:DisplayObject = DisplayObject(event.currentTarget); if(this._touchPointID >= 0) { var touch:Touch = event.getTouch(track, null, this._touchPointID); if(!touch) { return; } if(touch.phase === TouchPhase.MOVED && (!this._showThumb || this._trackInteractionMode === TRACK_INTERACTION_MODE_TO_VALUE_WITH_DRAG)) { touch.getLocation(this, HELPER_POINT); this.value = this.locationToValue(HELPER_POINT); } else if(touch.phase === TouchPhase.ENDED) { if(this._repeatTimer) { this._repeatTimer.stop(); } this._touchPointID = -1; this.isDragging = false; if(!this.liveDragging) { this.dispatchEventWith(Event.CHANGE); } this.dispatchEventWith(FeathersEventType.END_INTERACTION); } } else { touch = event.getTouch(track, TouchPhase.BEGAN); if(!touch) { return; } touch.getLocation(this, HELPER_POINT); this._touchPointID = touch.id; if(this._direction == Direction.VERTICAL) { this._thumbStartX = HELPER_POINT.x; this._thumbStartY = Math.min(this.actualHeight - this.thumb.height, Math.max(0, HELPER_POINT.y - this.thumb.height / 2)); } else //horizontal { this._thumbStartX = Math.min(this.actualWidth - this.thumb.width, Math.max(0, HELPER_POINT.x - this.thumb.width / 2)); this._thumbStartY = HELPER_POINT.y; } this._touchStartX = HELPER_POINT.x; this._touchStartY = HELPER_POINT.y; this._touchValue = this.locationToValue(HELPER_POINT); this.isDragging = true; this.dispatchEventWith(FeathersEventType.BEGIN_INTERACTION); if(this._showThumb && this._trackInteractionMode === TRACK_INTERACTION_MODE_BY_PAGE) { this.adjustPage(); this.startRepeatTimer(this.adjustPage); } else { this.value = this._touchValue; } } } /** * @private */ protected function thumb_touchHandler(event:TouchEvent):void { if(!this._isEnabled) { this._touchPointID = -1; return; } if(this._touchPointID >= 0) { var touch:Touch = event.getTouch(this.thumb, null, this._touchPointID); if(!touch) { return; } if(touch.phase == TouchPhase.MOVED) { var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); var claim:DisplayObject = exclusiveTouch.getClaim(this._touchPointID); if(claim != this) { if(claim) { //already claimed by another display object return; } else { exclusiveTouch.claimTouch(this._touchPointID, this); } } touch.getLocation(this, HELPER_POINT); this.value = this.locationToValue(HELPER_POINT); } else if(touch.phase == TouchPhase.ENDED) { this._touchPointID = -1; this.isDragging = false; if(!this.liveDragging) { this.dispatchEventWith(Event.CHANGE); } this.dispatchEventWith(FeathersEventType.END_INTERACTION); } } else { touch = event.getTouch(this.thumb, TouchPhase.BEGAN); if(!touch) { return; } touch.getLocation(this, HELPER_POINT); this._touchPointID = touch.id; this._thumbStartX = this.thumb.x; this._thumbStartY = this.thumb.y; this._touchStartX = HELPER_POINT.x; this._touchStartY = HELPER_POINT.y; this.isDragging = true; this.dispatchEventWith(FeathersEventType.BEGIN_INTERACTION); } } /** * @private */ protected function stage_keyDownHandler(event:KeyboardEvent):void { if(event.keyCode == Keyboard.HOME) { this.value = this._minimum; return; } if(event.keyCode == Keyboard.END) { this.value = this._maximum; return; } var page:Number = this._page; if(page !== page) //isNaN { page = this._step; } if(this._direction == Direction.VERTICAL) { if(event.keyCode == Keyboard.UP) { if(event.shiftKey) { this.value += page; } else { this.value += this._step; } } else if(event.keyCode == Keyboard.DOWN) { if(event.shiftKey) { this.value -= page; } else { this.value -= this._step; } } } else { if(event.keyCode == Keyboard.LEFT) { if(event.shiftKey) { this.value -= page; } else { this.value -= this._step; } } else if(event.keyCode == Keyboard.RIGHT) { if(event.shiftKey) { this.value += page; } else { this.value += this._step; } } } } /** * @private */ protected function repeatTimer_timerHandler(event:TimerEvent):void { var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); var claim:DisplayObject = exclusiveTouch.getClaim(this._touchPointID); if(claim && claim != this) { return; } if(this._repeatTimer.currentCount < 5) { return; } this.currentRepeatAction(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy