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

scaffold.libs_as.feathers.controls.ToggleSwitch.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.ITextBaselineControl;
	import feathers.core.ITextRenderer;
	import feathers.core.IToggle;
	import feathers.core.IValidating;
	import feathers.core.PropertyProxy;
	import feathers.skins.IStyleProvider;
	import feathers.system.DeviceCapabilities;

	import flash.geom.Point;
	import flash.ui.Keyboard;

	import starling.animation.Transitions;
	import starling.animation.Tween;
	import starling.core.Starling;
	import starling.display.DisplayObject;
	import starling.display.Quad;
	import starling.events.Event;
	import starling.events.KeyboardEvent;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;
	import starling.utils.SystemUtil;

	/**
	 * @copy feathers.core.IToggle#event:change
	 */
	[Event(name="change",type="starling.events.Event")]

	/**
	 * Similar to a light switch with on and off states. Generally considered an
	 * alternative to a check box.
	 *
	 * 

The following example programmatically selects a toggle switch and * listens for when the selection changes:

* * * var toggle:ToggleSwitch = new ToggleSwitch(); * toggle.isSelected = true; * toggle.addEventListener( Event.CHANGE, toggle_changeHandler ); * this.addChild( toggle ); * * @see ../../../help/toggle-switch.html How to use the Feathers ToggleSwitch component * @see feathers.controls.Check */ public class ToggleSwitch extends FeathersControl implements IToggle, IFocusDisplayObject, ITextBaselineControl { /** * @private */ private static const HELPER_POINT:Point = new Point(); /** * @private * The minimum physical distance (in inches) that a touch must move * before the scroller starts scrolling. */ private static const MINIMUM_DRAG_DISTANCE:Number = 0.04; /** * @private */ protected static const INVALIDATION_FLAG_THUMB_FACTORY:String = "thumbFactory"; /** * @private */ protected static const INVALIDATION_FLAG_ON_TRACK_FACTORY:String = "onTrackFactory"; /** * @private */ protected static const INVALIDATION_FLAG_OFF_TRACK_FACTORY:String = "offTrackFactory"; /** * The ON and OFF labels will be aligned to the middle vertically, * based on the full character height of the font. * * @see #labelAlign */ public static const LABEL_ALIGN_MIDDLE:String = "middle"; /** * The ON and OFF labels will be aligned to the middle vertically, * based on only the baseline value of the font. * * @see #labelAlign */ public static const LABEL_ALIGN_BASELINE:String = "baseline"; /** * @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_ON_OFF:String = "onOff"; /** * The default value added to the styleNameList of the off label. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_OFF_LABEL:String = "feathers-toggle-switch-off-label"; /** * The default value added to the styleNameList of the on label. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_ON_LABEL:String = "feathers-toggle-switch-on-label"; /** * The default value added to the styleNameList of the off track. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_OFF_TRACK:String = "feathers-toggle-switch-off-track"; /** * The default value added to the styleNameList of the on track. * * @see feathers.core.FeathersControl#styleNameList */ public static const DEFAULT_CHILD_STYLE_NAME_ON_TRACK:String = "feathers-toggle-switch-on-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-toggle-switch-thumb"; /** * The default IStyleProvider for all ToggleSwitch * 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 defaultOnTrackFactory():Button { return new Button(); } /** * @private */ protected static function defaultOffTrackFactory():Button { return new Button(); } /** * Constructor. */ public function ToggleSwitch() { super(); this.addEventListener(TouchEvent.TOUCH, toggleSwitch_touchHandler); this.addEventListener(Event.REMOVED_FROM_STAGE, toggleSwitch_removedFromStageHandler); } /** * The value added to the styleNameList of the off label * text renderer. This variable is protected so that * sub-classes can customize the on label text renderer style name in * their constructors instead of using the default style name defined by * DEFAULT_CHILD_STYLE_NAME_ON_LABEL. * * @see feathers.core.FeathersControl#styleNameList */ protected var onLabelStyleName:String = DEFAULT_CHILD_STYLE_NAME_ON_LABEL; /** * The value added to the styleNameList of the off label * text renderer. This variable is protected so that * sub-classes can customize the off label text renderer style name in * their constructors instead of using the default style name defined by * DEFAULT_CHILD_STYLE_NAME_OFF_LABEL. * * @see feathers.core.FeathersControl#styleNameList */ protected var offLabelStyleName:String = DEFAULT_CHILD_STYLE_NAME_OFF_LABEL; /** * The value added to the styleNameList of the on track. * This variable is protected so that sub-classes can * customize the on track style name in their constructors instead of * using the default style name defined by * DEFAULT_CHILD_STYLE_NAME_ON_TRACK. * *

To customize the on track style name without subclassing, see * customOnTrackStyleName.

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

To customize the off track style name without subclassing, see * customOffTrackStyleName.

* * @see #customOffTrackStyleName * @see feathers.core.FeathersControl#styleNameList */ protected var offTrackStyleName:String = DEFAULT_CHILD_STYLE_NAME_OFF_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 stylename 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 "on" text renderer sub-component. * * @see #labelFactory */ protected var onTextRenderer:ITextRenderer; /** * The "off" text renderer sub-component. * *

For internal use in subclasses.

* * @see #labelFactory */ protected var offTextRenderer:ITextRenderer; /** * The "on" track sub-component. * *

For internal use in subclasses.

* * @see #onTrackFactory * @see #createOnTrack() */ protected var onTrack:DisplayObject; /** * The "off" track sub-component. * *

For internal use in subclasses.

* * @see #offTrackFactory * @see #createOffTrack() */ protected var offTrack:DisplayObject; /** * @private */ override protected function get defaultStyleProvider():IStyleProvider { return ToggleSwitch.globalStyleProvider; } /** * @private */ protected var _paddingRight:Number = 0; /** * The minimum space, in pixels, between the switch's right edge and the * switch's content. * *

In the following example, the toggle switch's right padding is * set to 20 pixels:

* * * toggle.paddingRight = 20; * * @default 0 */ public function get paddingRight():Number { return this._paddingRight; } /** * @private */ public function set paddingRight(value:Number):void { if(this._paddingRight == value) { return; } this._paddingRight = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _paddingLeft:Number = 0; /** * The minimum space, in pixels, between the switch's left edge and the * switch's content. * *

In the following example, the toggle switch's left padding is * set to 20 pixels:

* * * toggle.paddingLeft = 20; * * @default 0 */ public function get paddingLeft():Number { return this._paddingLeft; } /** * @private */ public function set paddingLeft(value:Number):void { if(this._paddingLeft == value) { return; } this._paddingLeft = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _showLabels:Boolean = true; /** * Determines if the labels should be drawn. The onTrackSkin and * offTrackSkin backgrounds may include the text instead. * *

In the following example, the toggle switch's labels are hidden:

* * * toggle.showLabels = false; * * @default true */ public function get showLabels():Boolean { return _showLabels; } /** * @private */ public function set showLabels(value:Boolean):void { if(this._showLabels == value) { return; } this._showLabels = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _showThumb:Boolean = true; /** * Determines if the thumb should be displayed. This stops interaction * while still displaying the background. * *

In the following example, the toggle switch's thumb is hidden:

* * * toggle.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 _trackLayoutMode:String = TrackLayoutMode.SINGLE; [Inspectable(type="String",enumeration="single,split")] /** * Determines how the on and off track skins are positioned and sized. * *

In the following example, the toggle switch's track layout mode is * updated to use two tracks:

* * * toggle.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_ON_OFF) { value = TrackLayoutMode.SPLIT; } if(this._trackLayoutMode == value) { return; } this._trackLayoutMode = value; this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _defaultLabelProperties:PropertyProxy; /** * An object that stores properties for the toggle switch's label text * renderers when the toggle switch is enabled, and the properties will * be passed down to the text renderers when the toggle switch * validates. The available properties depend on which * ITextRenderer implementation is returned by * labelFactory (possibly onLabelFactory or * offLabelFactory instead). Refer to * feathers.core.ITextRenderer * for a list of available text renderer implementations. * *

In the following example, the toggle switch's default label * properties are updated (this example assumes that the label text * renderers are of type TextFieldTextRenderer):

* * * toggle.defaultLabelProperties.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * toggle.defaultLabelProperties.embedFonts = true; * * @default null * * @see #labelFactory * @see #onLabelFactory * @see #offLabelFactory * @see feathers.core.ITextRenderer * @see #onLabelProperties * @see #offLabelProperties * @see #disabledLabelProperties */ public function get defaultLabelProperties():Object { if(!this._defaultLabelProperties) { this._defaultLabelProperties = new PropertyProxy(childProperties_onChange); } return this._defaultLabelProperties; } /** * @private */ public function set defaultLabelProperties(value:Object):void { if(!(value is PropertyProxy)) { value = PropertyProxy.fromObject(value); } if(this._defaultLabelProperties) { this._defaultLabelProperties.removeOnChangeCallback(childProperties_onChange); } this._defaultLabelProperties = PropertyProxy(value); if(this._defaultLabelProperties) { this._defaultLabelProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _disabledLabelProperties:PropertyProxy; /** * An object that stores properties for the toggle switch's label text * renderers when the toggle switch is disabled, and the properties will * be passed down to the text renderers when the toggle switch * validates. The available properties depend on which * ITextRenderer implementation is returned by * labelFactory (possibly onLabelFactory or * offLabelFactory instead). Refer to * feathers.core.ITextRenderer * for a list of available text renderer implementations. * *

In the following example, the toggle switch's disabled label * properties are updated (this example assumes that the label text * renderers are of type TextFieldTextRenderer):

* * * toggle.disabledLabelProperties.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * toggle.disabledLabelProperties.embedFonts = true; * * @default null * * @see #labelFactory * @see #onLabelFactory * @see #offLabelFactory * @see feathers.core.ITextRenderer * @see #defaultLabelProperties */ public function get disabledLabelProperties():Object { if(!this._disabledLabelProperties) { this._disabledLabelProperties = new PropertyProxy(childProperties_onChange); } return this._disabledLabelProperties; } /** * @private */ public function set disabledLabelProperties(value:Object):void { if(!(value is PropertyProxy)) { value = PropertyProxy.fromObject(value); } if(this._disabledLabelProperties) { this._disabledLabelProperties.removeOnChangeCallback(childProperties_onChange); } this._disabledLabelProperties = PropertyProxy(value); if(this._disabledLabelProperties) { this._disabledLabelProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _onLabelProperties:PropertyProxy; /** * An object that stores properties for the toggle switch's "on" label * text renderer, and the properties will be passed down to the text * renderer when the toggle switch validates. If null, then * defaultLabelProperties is used instead. * *

The available properties depend on which * ITextRenderer implementation is returned by * labelFactory (possibly onLabelFactory * instead). Refer to * feathers.core.ITextRenderer * for a list of available text renderer implementations.

* *

In the following example, the toggle switch's on label properties * are updated (this example assumes that the on label text renderer is a * TextFieldTextRenderer):

* * * toggle.onLabelProperties.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * toggle.onLabelProperties.embedFonts = true; * * @default null * * @see #labelFactory * @see feathers.core.ITextRenderer * @see #defaultLabelProperties */ public function get onLabelProperties():Object { if(!this._onLabelProperties) { this._onLabelProperties = new PropertyProxy(childProperties_onChange); } return this._onLabelProperties; } /** * @private */ public function set onLabelProperties(value:Object):void { if(!(value is PropertyProxy)) { value = PropertyProxy.fromObject(value); } if(this._onLabelProperties) { this._onLabelProperties.removeOnChangeCallback(childProperties_onChange); } this._onLabelProperties = PropertyProxy(value); if(this._onLabelProperties) { this._onLabelProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _offLabelProperties:PropertyProxy; /** * An object that stores properties for the toggle switch's "off" label * text renderer, and the properties will be passed down to the text * renderer when the toggle switch validates. If null, then * defaultLabelProperties is used instead. * *

The available properties depend on which * ITextRenderer implementation is returned by * labelFactory (possibly offLabelFactory * instead). Refer to * feathers.core.ITextRenderer * for a list of available text renderer implementations.

* *

In the following example, the toggle switch's off label properties * are updated (this example assumes that the off label text renderer is a * TextFieldTextRenderer):

* * * toggle.offLabelProperties.textFormat = new TextFormat( "Source Sans Pro", 16, 0x333333 ); * toggle.offLabelProperties.embedFonts = true; * * @default null * * @see #labelFactory * @see feathers.core.ITextRenderer * @see #defaultLabelProperties */ public function get offLabelProperties():Object { if(!this._offLabelProperties) { this._offLabelProperties = new PropertyProxy(childProperties_onChange); } return this._offLabelProperties; } /** * @private */ public function set offLabelProperties(value:Object):void { if(!(value is PropertyProxy)) { value = PropertyProxy.fromObject(value); } if(this._offLabelProperties) { this._offLabelProperties.removeOnChangeCallback(childProperties_onChange); } this._offLabelProperties = PropertyProxy(value); if(this._offLabelProperties) { this._offLabelProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _labelAlign:String = LABEL_ALIGN_BASELINE; [Inspectable(type="String",enumeration="baseline,middle")] /** * The vertical alignment of the label. * *

In the following example, the toggle switch's label alignment is * updated:

* * * toggle.labelAlign = ToggleSwitch.LABEL_ALIGN_MIDDLE; * * @default ToggleSwitch.LABEL_ALIGN_BASELINE * * @see #LABEL_ALIGN_BASELINE * @see #LABEL_ALIGN_MIDDLE */ public function get labelAlign():String { return this._labelAlign; } /** * @private */ public function set labelAlign(value:String):void { if(this._labelAlign == value) { return; } this._labelAlign = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _labelFactory:Function; /** * A function used to instantiate the toggle switch's label text * renderer sub-components, if specific factories for those label text * renderers are not provided. The label text renderers must be * instances of ITextRenderer. This factory can be used to * change properties of the label text renderers when they are first * created. For instance, if you are skinning Feathers components * without a theme, you might use this factory to style the label text * renderers. * *

The factory should have the following function signature:

*
function():ITextRenderer
* *

In the following example, the toggle switch uses a custom label * factory:

* * * toggle.labelFactory = function():ITextRenderer * { * return new TextFieldTextRenderer(); * } * * @default null * * @see #onLabelFactory * @see #offLabelFactory * @see feathers.core.ITextRenderer * @see feathers.core.FeathersControl#defaultTextRendererFactory */ public function get labelFactory():Function { return this._labelFactory; } /** * @private */ public function set labelFactory(value:Function):void { if(this._labelFactory == value) { return; } this._labelFactory = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var _onLabelFactory:Function; /** * A function used to instantiate the toggle switch's on label text * renderer sub-component. The on label text renderer must be an * instance of ITextRenderer. This factory can be used to * change properties of the on label text renderer when it is first * created. For instance, if you are skinning Feathers components * without a theme, you might use this factory to style the on label * text renderer. * *

If an onLabelFactory is not provided, the default * labelFactory will be used.

* *

The factory should have the following function signature:

*
function():ITextRenderer
* *

In the following example, the toggle switch uses a custom on label * factory:

* * * toggle.onLabelFactory = function():ITextRenderer * { * return new TextFieldTextRenderer(); * } * * @default null * * @see #labelFactory * @see #offLabelFactory * @see feathers.core.ITextRenderer * @see feathers.core.FeathersControl#defaultTextRendererFactory */ public function get onLabelFactory():Function { return this._onLabelFactory; } /** * @private */ public function set onLabelFactory(value:Function):void { if(this._onLabelFactory == value) { return; } this._onLabelFactory = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var _customOnLabelStyleName:String; /** * A style name to add to the toggle switch's on label text renderer * sub-component. Typically used by a theme to provide different styles * to different buttons. * *

In the following example, a custom on label style name is passed * to the toggle switch:

* * * toggle.customOnLabelStyleName = "my-custom-toggle-on-label"; * *

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

* * * getStyleProviderForClass( BitmapFontTextRenderer ).setFunctionForStyleName( "my-custom-toggle-on-label", setCustomToggleSwitchOnLabelStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_ON_LABEL * @see feathers.core.FeathersControl#styleNameList * @see #onLabelFactory */ public function get customOnLabelStyleName():String { return this._customOnLabelStyleName; } /** * @private */ public function set customOnLabelStyleName(value:String):void { if(this._customOnLabelStyleName == value) { return; } this._customOnLabelStyleName = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var _offLabelFactory:Function; /** * A function used to instantiate the toggle switch's off label text * renderer sub-component. The off label text renderer must be an * instance of ITextRenderer. This factory can be used to * change properties of the off label text renderer when it is first * created. For instance, if you are skinning Feathers components * without a theme, you might use this factory to style the off label * text renderer. * *

If an offLabelFactory is not provided, the default * labelFactory will be used.

* *

The factory should have the following function signature:

*
function():ITextRenderer
* *

In the following example, the toggle switch uses a custom on label * factory:

* * * toggle.offLabelFactory = function():ITextRenderer * { * return new TextFieldTextRenderer(); * } * * @default null * * @see #labelFactory * @see #onLabelFactory * @see feathers.core.ITextRenderer * @see feathers.core.FeathersControl#defaultTextRendererFactory */ public function get offLabelFactory():Function { return this._offLabelFactory; } /** * @private */ public function set offLabelFactory(value:Function):void { if(this._offLabelFactory == value) { return; } this._offLabelFactory = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var _customOffLabelStyleName:String; /** * A style name to add to the toggle switch's off label text renderer * sub-component. Typically used by a theme to provide different styles * to different toggle switches. * *

In the following example, a custom off label style name is passed * to the toggle switch:

* * * toggle.customOffLabelStyleName = "my-custom-toggle-off-label"; * *

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

* * * getStyleProviderForClass( BitmapFontTextRenderer ).setFunctionForStyleName( "my-custom-toggle-off-label", setCustomToggleSwitchOffLabelStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_OFF_LABEL * @see feathers.core.FeathersControl#styleNameList * @see #offLabelFactory */ public function get customOffLabelStyleName():String { return this._customOffLabelStyleName; } /** * @private */ public function set customOffLabelStyleName(value:String):void { if(this._customOffLabelStyleName == value) { return; } this._customOffLabelStyleName = value; this.invalidate(INVALIDATION_FLAG_TEXT_RENDERER); } /** * @private */ protected var onTrackSkinOriginalWidth:Number = NaN; /** * @private */ protected var onTrackSkinOriginalHeight:Number = NaN; /** * @private */ protected var offTrackSkinOriginalWidth:Number = NaN; /** * @private */ protected var offTrackSkinOriginalHeight:Number = NaN; /** * @private */ protected var _isSelected:Boolean = false; /** * Indicates if the toggle switch is selected (ON) or not (OFF). * *

In the following example, the toggle switch is selected:

* * * toggle.isSelected = true; * * @default false * * @see #setSelectionWithAnimation() */ public function get isSelected():Boolean { return this._isSelected; } /** * @private */ public function set isSelected(value:Boolean):void { this._animateSelectionChange = false; if(this._isSelected == value) { return; } this._isSelected = value; this.invalidate(INVALIDATION_FLAG_SELECTED); this.dispatchEventWith(Event.CHANGE); } /** * @private */ protected var _toggleThumbSelection:Boolean = false; /** * Determines if the isSelected property of the thumb * is updated to match the isSelected property of the * toggle switch, if the class used to create the thumb implements the * IToggle interface. Useful for skinning to provide a * different appearance for the thumb based on whether the toggle switch * is selected or not. * *

In the following example, the thumb selection is toggled:

* * * toggle.toggleThumbSelection = true; * * @default false * * @see feathers.core.IToggle * @see feathers.controls.ToggleButton */ public function get toggleThumbSelection():Boolean { return this._toggleThumbSelection; } /** * @private */ public function set toggleThumbSelection(value:Boolean):void { if(this._toggleThumbSelection == value) { return; } this._toggleThumbSelection = value; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * @private */ protected var _toggleDuration:Number = 0.15; /** * The duration, in seconds, of the animation when the toggle switch * is toggled and animates the position of the thumb. * *

In the following example, the duration of the toggle switch thumb * animation is updated:

* * * toggle.toggleDuration = 0.5; * * @default 0.15 */ public function get toggleDuration():Number { return this._toggleDuration; } /** * @private */ public function set toggleDuration(value:Number):void { this._toggleDuration = value; } /** * @private */ protected var _toggleEase:Object = Transitions.EASE_OUT; /** * The easing function used for toggle animations. * *

In the following example, the easing function used by the toggle * switch's thumb animation is updated:

* * * toggle.toggleEase = Transitions.EASE_IN_OUT; * * @default starling.animation.Transitions.EASE_OUT * * @see http://doc.starling-framework.org/core/starling/animation/Transitions.html starling.animation.Transitions */ public function get toggleEase():Object { return this._toggleEase; } /** * @private */ public function set toggleEase(value:Object):void { this._toggleEase = value; } /** * @private */ protected var _onText:String = "ON"; /** * The text to display in the ON label. * *

In the following example, the toggle switch's on label text is * updated:

* * * toggle.onText = "on"; * * @default "ON" */ public function get onText():String { return this._onText; } /** * @private */ public function set onText(value:String):void { if(value === null) { value = ""; } if(this._onText == value) { return; } this._onText = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _offText:String = "OFF"; /** * The text to display in the OFF label. * *

In the following example, the toggle switch's off label text is * updated:

* * * toggle.offText = "off"; * * @default "OFF" */ public function get offText():String { return this._offText; } /** * @private */ public function set offText(value:String):void { if(value === null) { value = ""; } if(this._offText == value) { return; } this._offText = value; this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _toggleTween:Tween; /** * @private */ protected var _ignoreTapHandler:Boolean = false; /** * @private */ protected var _touchPointID:int = -1; /** * @private */ protected var _thumbStartX:Number; /** * @private */ protected var _touchStartX:Number; /** * @private */ protected var _animateSelectionChange:Boolean = false; /** * @private */ protected var _onTrackFactory:Function; /** * A function used to generate the toggle switch's "on" track * sub-component. The "on" track must be an instance of * Button. This factory can be used to change properties on * the "on" 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 "on" track. * *

The function should have the following signature:

*
function():Button
* *

In the following example, a custom on track factory is passed to * the toggle switch:

* * * toggle.onTrackFactory = function():Button * { * var onTrack:Button = new Button(); * onTrack.defaultSkin = new Image( texture ); * return onTrack; * }; * * @default null * * @see feathers.controls.Button * @see #onTrackProperties */ public function get onTrackFactory():Function { return this._onTrackFactory; } /** * @private */ public function set onTrackFactory(value:Function):void { if(this._onTrackFactory == value) { return; } this._onTrackFactory = value; this.invalidate(INVALIDATION_FLAG_ON_TRACK_FACTORY); } /** * @private */ protected var _customOnTrackStyleName:String; /** * A style name to add to the toggle switch's on track sub-component. * Typically used by a theme to provide different styles to different * toggle switches. * *

In the following example, a custom on track style name is passed to * the toggle switch:

* * * toggle.customOnTrackStyleName = "my-custom-on-track"; * *

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

* * * getStyleProviderForClass( Button ).setFunctionForStyleName( "my-custom-on-track", setCustomOnTrackStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_ON_TRACK * @see feathers.core.FeathersControl#styleNameList * @see #onTrackFactory * @see #onTrackProperties */ public function get customOnTrackStyleName():String { return this._customOnTrackStyleName; } /** * @private */ public function set customOnTrackStyleName(value:String):void { if(this._customOnTrackStyleName == value) { return; } this._customOnTrackStyleName = value; this.invalidate(INVALIDATION_FLAG_ON_TRACK_FACTORY); } /** * @private */ protected var _onTrackProperties:PropertyProxy; /** * An object that stores properties for the toggle switch's "on" track, * and the properties will be passed down to the "on" track when the * toggle switch 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 onTrackFactory function * instead of using onTrackProperties will result in * better performance.

* *

In the following example, the toggle switch's on track properties * are updated:

* * * toggle.onTrackProperties.defaultSkin = new Image( texture ); * * @default null * * @see feathers.controls.Button * @see #onTrackFactory */ public function get onTrackProperties():Object { if(!this._onTrackProperties) { this._onTrackProperties = new PropertyProxy(childProperties_onChange); } return this._onTrackProperties; } /** * @private */ public function set onTrackProperties(value:Object):void { if(this._onTrackProperties == 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._onTrackProperties) { this._onTrackProperties.removeOnChangeCallback(childProperties_onChange); } this._onTrackProperties = PropertyProxy(value); if(this._onTrackProperties) { this._onTrackProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _offTrackFactory:Function; /** * A function used to generate the toggle switch's "off" track * sub-component. The "off" track must be an instance of * Button. This factory can be used to change properties on * the "off" 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 "off" track. * *

The function should have the following signature:

*
function():Button
* *

In the following example, a custom off track factory is passed to * the toggle switch:

* * * toggle.offTrackFactory = function():Button * { * var offTrack:Button = new Button(); * offTrack.defaultSkin = new Image( texture ); * return offTrack; * }; * * @default null * * @see feathers.controls.Button * @see #offTrackProperties */ public function get offTrackFactory():Function { return this._offTrackFactory; } /** * @private */ public function set offTrackFactory(value:Function):void { if(this._offTrackFactory == value) { return; } this._offTrackFactory = value; this.invalidate(INVALIDATION_FLAG_OFF_TRACK_FACTORY); } /** * @private */ protected var _customOffTrackStyleName:String; /** * A style name to add to the toggle switch's off track sub-component. * Typically used by a theme to provide different styles to different * toggle switches. * *

In the following example, a custom off track style name is passed * to the toggle switch:

* * * toggle.customOffTrackStyleName = "my-custom-off-track"; * *

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

* * * getStyleProviderForClass( Button ).setFunctionForStyleName( "my-custom-off-track", setCustomOffTrackStyles ); * * @default null * * @see #DEFAULT_CHILD_STYLE_NAME_OFF_TRACK * @see feathers.core.FeathersControl#styleNameList * @see #offTrackFactory * @see #offTrackProperties */ public function get customOffTrackStyleName():String { return this._customOffTrackStyleName; } /** * @private */ public function set customOffTrackStyleName(value:String):void { if(this._customOffTrackStyleName == value) { return; } this._customOffTrackStyleName = value; this.invalidate(INVALIDATION_FLAG_OFF_TRACK_FACTORY); } /** * @private */ protected var _offTrackProperties:PropertyProxy; /** * An object that stores properties for the toggle switch's "off" track, * and the properties will be passed down to the "off" track when the * toggle switch 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 offTrackFactory function * instead of using offTrackProperties will result in * better performance.

* *

In the following example, the toggle switch's off track properties * are updated:

* * * toggle.offTrackProperties.defaultSkin = new Image( texture ); * * @default null * * @see feathers.controls.Button * @see #offTrackFactory */ public function get offTrackProperties():Object { if(!this._offTrackProperties) { this._offTrackProperties = new PropertyProxy(childProperties_onChange); } return this._offTrackProperties; } /** * @private */ public function set offTrackProperties(value:Object):void { if(this._offTrackProperties == 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._offTrackProperties) { this._offTrackProperties.removeOnChangeCallback(childProperties_onChange); } this._offTrackProperties = PropertyProxy(value); if(this._offTrackProperties) { this._offTrackProperties.addOnChangeCallback(childProperties_onChange); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _thumbFactory:Function; /** * A function used to generate the toggle switch's thumb sub-component. * This 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 thumbFactory to set * skins and text 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 * toggle switch:

* * * toggle.thumbFactory = function():Button * { * var button:Button = new Button(); * button.defaultSkin = new Image( texture ); * return button; * }; * * @default null * * @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 toggle switch's thumb sub-component. * Typically used by a theme to provide different styles to different * toggle switches. * *

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

* * * toggle.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 toggle switch's thumb * sub-component, and the properties will be passed down to the thumb * when the toggle switch 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 toggle switch's thumb properties * are updated:

* * * toggle.thumbProperties.defaultSkin = new Image( texture ); * * @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); } /** * @inheritDoc */ public function get baseline():Number { if(!this.onTextRenderer) { return this.scaledActualHeight; } return this.scaleY * (this.onTextRenderer.y + this.onTextRenderer.baseline); } /** * Changes the isSelected property, but animates the thumb * to the new position, as if the user tapped the toggle switch. * * @see #isSelected */ public function setSelectionWithAnimation(isSelected:Boolean):void { if(this._isSelected == isSelected) { return; } this.isSelected = isSelected; this._animateSelectionChange = true; } /** * @private */ override protected function draw():void { var selectionInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SELECTED); 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 textRendererInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_TEXT_RENDERER); var thumbFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_THUMB_FACTORY); var onTrackFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_ON_TRACK_FACTORY); var offTrackFactoryInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_OFF_TRACK_FACTORY); if(thumbFactoryInvalid) { this.createThumb(); } if(onTrackFactoryInvalid) { this.createOnTrack(); } if(offTrackFactoryInvalid || layoutInvalid) { this.createOffTrack(); } if(textRendererInvalid) { this.createLabels(); } if(textRendererInvalid || stylesInvalid || stateInvalid) { this.refreshOnLabelStyles(); this.refreshOffLabelStyles(); } if(thumbFactoryInvalid || stylesInvalid) { this.refreshThumbStyles(); } if(onTrackFactoryInvalid || stylesInvalid) { this.refreshOnTrackStyles(); } if((offTrackFactoryInvalid || layoutInvalid || stylesInvalid) && this.offTrack) { this.refreshOffTrackStyles(); } if(stateInvalid || layoutInvalid || thumbFactoryInvalid || onTrackFactoryInvalid || onTrackFactoryInvalid || textRendererInvalid) { this.refreshEnabled(); } sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid; if(sizeInvalid || stylesInvalid || selectionInvalid) { this.updateSelection(); } 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.onTrackSkinOriginalWidth !== this.onTrackSkinOriginalWidth || //isNaN this.onTrackSkinOriginalHeight !== this.onTrackSkinOriginalHeight) //isNaN { if(this.onTrack is IValidating) { IValidating(this.onTrack).validate(); } this.onTrackSkinOriginalWidth = this.onTrack.width; this.onTrackSkinOriginalHeight = this.onTrack.height; } if(this.offTrack) { if(this.offTrackSkinOriginalWidth !== this.offTrackSkinOriginalWidth || //isNaN this.offTrackSkinOriginalHeight !== this.offTrackSkinOriginalHeight) //isNaN { if(this.offTrack is IValidating) { IValidating(this.offTrack).validate(); } this.offTrackSkinOriginalWidth = this.offTrack.width; this.offTrackSkinOriginalHeight = this.offTrack.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.offTrack) { newWidth = Math.min(this.onTrackSkinOriginalWidth, this.offTrackSkinOriginalWidth) + this.thumb.width / 2; } else { newWidth = this.onTrackSkinOriginalWidth; } } if(needsHeight) { if(this.offTrack) { newHeight = Math.max(this.onTrackSkinOriginalHeight, this.offTrackSkinOriginalHeight); } else { newHeight = this.onTrackSkinOriginalHeight; } } 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 onTrack 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 #onTrack * @see #onTrackFactory * @see #customOnTrackStyleName */ protected function createOnTrack():void { if(this.onTrack) { this.onTrack.removeFromParent(true); this.onTrack = null; } var factory:Function = this._onTrackFactory != null ? this._onTrackFactory : defaultOnTrackFactory; var onTrackStyleName:String = this._customOnTrackStyleName != null ? this._customOnTrackStyleName : this.onTrackStyleName; var onTrack:Button = Button(factory()); onTrack.styleNameList.add(onTrackStyleName); onTrack.keepDownStateOnRollOut = true; this.addChildAt(onTrack, 0); this.onTrack = onTrack; } /** * Creates and adds the offTrack sub-component and * removes the old instance, if one exists. If the off track is not * needed, it will not be created. * *

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

* * @see #offTrack * @see #offTrackFactory * @see #customOffTrackStyleName */ protected function createOffTrack():void { if(this._trackLayoutMode == TrackLayoutMode.SPLIT) { if(this.offTrack) { this.offTrack.removeFromParent(true); this.offTrack = null; } var factory:Function = this._offTrackFactory != null ? this._offTrackFactory : defaultOffTrackFactory; var offTrackStyleName:String = this._customOffTrackStyleName != null ? this._customOffTrackStyleName : this.offTrackStyleName; var offTrack:Button = Button(factory()); offTrack.styleNameList.add(offTrackStyleName); offTrack.keepDownStateOnRollOut = true; this.addChildAt(offTrack, 1); this.offTrack = offTrack; } else if(this.offTrack) //single { this.offTrack.removeFromParent(true); this.offTrack = null; } } /** * @private */ protected function createLabels():void { if(this.offTextRenderer) { this.removeChild(DisplayObject(this.offTextRenderer), true); this.offTextRenderer = null; } if(this.onTextRenderer) { this.removeChild(DisplayObject(this.onTextRenderer), true); this.onTextRenderer = null; } var index:int = this.getChildIndex(this.thumb); var offLabelFactory:Function = this._offLabelFactory; if(offLabelFactory == null) { offLabelFactory = this._labelFactory; } if(offLabelFactory == null) { offLabelFactory = FeathersControl.defaultTextRendererFactory; } this.offTextRenderer = ITextRenderer(offLabelFactory()); var offLabelStyleName:String = this._customOffLabelStyleName != null ? this._customOffLabelStyleName : this.offLabelStyleName; this.offTextRenderer.styleNameList.add(offLabelStyleName); var mask:Quad = new Quad(1, 1, 0xff00ff); //the initial dimensions cannot be 0 or there's a runtime error mask.width = 0; mask.height = 0; this.offTextRenderer.mask = mask; this.addChildAt(DisplayObject(this.offTextRenderer), index); var onLabelFactory:Function = this._onLabelFactory; if(onLabelFactory == null) { onLabelFactory = this._labelFactory; } if(onLabelFactory == null) { onLabelFactory = FeathersControl.defaultTextRendererFactory; } this.onTextRenderer = ITextRenderer(onLabelFactory()); var onLabelStyleName:String = this._customOnLabelStyleName != null ? this._customOnLabelStyleName : this.onLabelStyleName; this.onTextRenderer.styleNameList.add(onLabelStyleName); mask = new Quad(1, 1, 0xff00ff); //the initial dimensions cannot be 0 or there's a runtime error mask.width = 0; mask.height = 0; this.onTextRenderer.mask = mask; this.addChildAt(DisplayObject(this.onTextRenderer), index); } /** * @private */ protected function layoutChildren():void { if(this.thumb is IValidating) { IValidating(this.thumb).validate(); } this.thumb.y = (this.actualHeight - this.thumb.height) / 2; var maxLabelWidth:Number = Math.max(0, this.actualWidth - this.thumb.width - this._paddingLeft - this._paddingRight); var totalLabelHeight:Number = Math.max(this.onTextRenderer.height, this.offTextRenderer.height); var labelHeight:Number; if(this._labelAlign == LABEL_ALIGN_MIDDLE) { labelHeight = totalLabelHeight; } else //baseline { labelHeight = Math.max(this.onTextRenderer.baseline, this.offTextRenderer.baseline); } var mask:DisplayObject = this.onTextRenderer.mask; mask.width = maxLabelWidth; mask.height = totalLabelHeight; this.onTextRenderer.y = (this.actualHeight - labelHeight) / 2; mask = this.offTextRenderer.mask; mask.width = maxLabelWidth; mask.height = totalLabelHeight; this.offTextRenderer.y = (this.actualHeight - labelHeight) / 2; this.layoutTracks(); } /** * @private */ protected function layoutTracks():void { var maxLabelWidth:Number = Math.max(0, this.actualWidth - this.thumb.width - this._paddingLeft - this._paddingRight); var thumbOffset:Number = this.thumb.x - this._paddingLeft; var onScrollOffset:Number = maxLabelWidth - thumbOffset - (maxLabelWidth - this.onTextRenderer.width) / 2; var currentMask:DisplayObject = this.onTextRenderer.mask; currentMask.x = onScrollOffset; this.onTextRenderer.x = this._paddingLeft - onScrollOffset; var offScrollOffset:Number = -thumbOffset - (maxLabelWidth - this.offTextRenderer.width) / 2; currentMask = this.offTextRenderer.mask; currentMask.x = offScrollOffset; this.offTextRenderer.x = this.actualWidth - this._paddingRight - maxLabelWidth - offScrollOffset; if(this._trackLayoutMode == TrackLayoutMode.SPLIT) { this.layoutTrackWithOnOff(); } else { this.layoutTrackWithSingle(); } } /** * @private */ protected function updateSelection():void { if(this.thumb is IToggle) { var toggleThumb:IToggle = IToggle(this.thumb); if(this._toggleThumbSelection) { toggleThumb.isSelected = this._isSelected; } else { toggleThumb.isSelected = false; } } if(this.thumb is IValidating) { IValidating(this.thumb).validate(); } var xPosition:Number = this._paddingLeft; if(this._isSelected) { xPosition = this.actualWidth - this.thumb.width - this._paddingRight; } //stop the tween, no matter what if(this._toggleTween) { Starling.juggler.remove(this._toggleTween); this._toggleTween = null; } if(this._animateSelectionChange) { this._toggleTween = new Tween(this.thumb, this._toggleDuration, this._toggleEase); this._toggleTween.animate("x", xPosition); this._toggleTween.onUpdate = selectionTween_onUpdate; this._toggleTween.onComplete = selectionTween_onComplete; Starling.juggler.add(this._toggleTween); } else { this.thumb.x = xPosition; } this._animateSelectionChange = false; } /** * @private */ protected function refreshOnLabelStyles():void { //no need to style the label field if there's no text to display if(!this._showLabels || !this._showThumb) { this.onTextRenderer.visible = false; return; } var properties:PropertyProxy; if(!this._isEnabled) { properties = this._disabledLabelProperties; } if(!properties && this._onLabelProperties) { properties = this._onLabelProperties; } if(!properties) { properties = this._defaultLabelProperties; } this.onTextRenderer.text = this._onText; if(properties) { var displayRenderer:DisplayObject = DisplayObject(this.onTextRenderer); for(var propertyName:String in properties) { var propertyValue:Object = properties[propertyName]; displayRenderer[propertyName] = propertyValue; } } this.onTextRenderer.validate(); this.onTextRenderer.visible = true; } /** * @private */ protected function refreshOffLabelStyles():void { //no need to style the label field if there's no text to display if(!this._showLabels || !this._showThumb) { this.offTextRenderer.visible = false; return; } var properties:PropertyProxy; if(!this._isEnabled) { properties = this._disabledLabelProperties; } if(!properties && this._offLabelProperties) { properties = this._offLabelProperties; } if(!properties) { properties = this._defaultLabelProperties; } this.offTextRenderer.text = this._offText; if(properties) { var displayRenderer:DisplayObject = DisplayObject(this.offTextRenderer); for(var propertyName:String in properties) { var propertyValue:Object = properties[propertyName]; displayRenderer[propertyName] = propertyValue; } } this.offTextRenderer.validate(); this.offTextRenderer.visible = true; } /** * @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 refreshOnTrackStyles():void { for(var propertyName:String in this._onTrackProperties) { var propertyValue:Object = this._onTrackProperties[propertyName]; this.onTrack[propertyName] = propertyValue; } } /** * @private */ protected function refreshOffTrackStyles():void { if(!this.offTrack) { return; } for(var propertyName:String in this._offTrackProperties) { var propertyValue:Object = this._offTrackProperties[propertyName]; this.offTrack[propertyName] = propertyValue; } } /** * @private */ protected function refreshEnabled():void { if(this.thumb is IFeathersControl) { IFeathersControl(this.thumb).isEnabled = this._isEnabled; } if(this.onTrack is IFeathersControl) { IFeathersControl(this.onTrack).isEnabled = this._isEnabled; } if(this.offTrack is IFeathersControl) { IFeathersControl(this.offTrack).isEnabled = this._isEnabled; } this.onTextRenderer.isEnabled = this._isEnabled; this.offTextRenderer.isEnabled = this._isEnabled; } /** * @private */ protected function layoutTrackWithOnOff():void { this.onTrack.x = 0; this.onTrack.y = 0; this.onTrack.width = this.thumb.x + this.thumb.width / 2; this.onTrack.height = this.actualHeight; this.offTrack.x = this.onTrack.width; this.offTrack.y = 0; this.offTrack.width = this.actualWidth - this.offTrack.x; this.offTrack.height = this.actualHeight; //final validation to avoid juggler next frame issues if(this.onTrack is IValidating) { IValidating(this.onTrack).validate(); } if(this.offTrack is IValidating) { IValidating(this.offTrack).validate(); } } /** * @private */ protected function layoutTrackWithSingle():void { this.onTrack.x = 0; this.onTrack.y = 0; this.onTrack.width = this.actualWidth; this.onTrack.height = this.actualHeight; //final validation to avoid juggler next frame issues if(this.onTrack is IValidating) { IValidating(this.onTrack).validate(); } } /** * @private */ protected function childProperties_onChange(proxy:PropertyProxy, name:Object):void { this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected function toggleSwitch_removedFromStageHandler(event:Event):void { this._touchPointID = -1; } /** * @private */ override protected function focusInHandler(event:Event):void { super.focusInHandler(event); this.stage.addEventListener(KeyboardEvent.KEY_DOWN, stage_keyDownHandler); this.stage.addEventListener(KeyboardEvent.KEY_UP, stage_keyUpHandler); } /** * @private */ override protected function focusOutHandler(event:Event):void { super.focusOutHandler(event); this.stage.removeEventListener(KeyboardEvent.KEY_DOWN, stage_keyDownHandler); this.stage.removeEventListener(KeyboardEvent.KEY_UP, stage_keyUpHandler); } /** * @private */ protected function toggleSwitch_touchHandler(event:TouchEvent):void { if(this._ignoreTapHandler) { this._ignoreTapHandler = false; return; } if(!this._isEnabled) { this._touchPointID = -1; return; } var touch:Touch = event.getTouch(this, TouchPhase.ENDED); if(!touch) { return; } this._touchPointID = -1; touch.getLocation(this.stage, HELPER_POINT); var isInBounds:Boolean = this.contains(this.stage.hitTest(HELPER_POINT)); if(isInBounds) { this.setSelectionWithAnimation(!this._isSelected); } } /** * @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; } touch.getLocation(this, HELPER_POINT); var trackScrollableWidth:Number = this.actualWidth - this._paddingLeft - this._paddingRight - this.thumb.width; if(touch.phase == TouchPhase.MOVED) { var xOffset:Number = HELPER_POINT.x - this._touchStartX; var xPosition:Number = Math.min(Math.max(this._paddingLeft, this._thumbStartX + xOffset), this._paddingLeft + trackScrollableWidth); this.thumb.x = xPosition; this.layoutTracks(); } else if(touch.phase == TouchPhase.ENDED) { var pixelsMoved:Number = Math.abs(HELPER_POINT.x - this._touchStartX); var inchesMoved:Number = pixelsMoved / DeviceCapabilities.dpi; if(inchesMoved > MINIMUM_DRAG_DISTANCE || (SystemUtil.isDesktop && pixelsMoved >= 1)) { this._touchPointID = -1; this._ignoreTapHandler = true; this.setSelectionWithAnimation(this.thumb.x > (this._paddingLeft + trackScrollableWidth / 2)); //we still need to invalidate, even if there's no change //because the thumb may be in the middle! this.invalidate(INVALIDATION_FLAG_SELECTED); } } } 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._touchStartX = HELPER_POINT.x; } } /** * @private */ protected function stage_keyDownHandler(event:KeyboardEvent):void { if(event.keyCode == Keyboard.ESCAPE) { this._touchPointID = -1; } if(this._touchPointID >= 0 || event.keyCode != Keyboard.SPACE) { return; } this._touchPointID = int.MAX_VALUE; } /** * @private */ protected function stage_keyUpHandler(event:KeyboardEvent):void { if(this._touchPointID != int.MAX_VALUE || event.keyCode != Keyboard.SPACE) { return; } this._touchPointID = -1; this.setSelectionWithAnimation(!this._isSelected); } /** * @private */ protected function selectionTween_onUpdate():void { this.layoutTracks(); } /** * @private */ protected function selectionTween_onComplete():void { this._toggleTween = null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy