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

scaffold.libs_as.feathers.controls.Drawers.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.controls.supportClasses.BaseScreenNavigator;
	import feathers.core.FeathersControl;
	import feathers.core.IFeathersControl;
	import feathers.core.IValidating;
	import feathers.events.ExclusiveTouch;
	import feathers.events.FeathersEventType;
	import feathers.skins.IStyleProvider;
	import feathers.system.DeviceCapabilities;
	import feathers.utils.display.getDisplayObjectDepthFromStage;
	import feathers.utils.math.roundToNearest;

	import flash.events.KeyboardEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	import flash.utils.getTimer;

	import starling.animation.Transitions;
	import starling.animation.Tween;
	import starling.core.Starling;
	import starling.display.DisplayObject;
	import starling.display.DisplayObjectContainer;
	import starling.display.Quad;
	import starling.display.Sprite;
	import starling.display.Stage;
	import starling.events.Event;
	import starling.events.EventDispatcher;
	import starling.events.ResizeEvent;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;

	/**
	 * Dispatched when the user starts dragging the content to open or close a
	 * drawer.
	 *
	 * 

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 * @see #event:endInteraction feathers.events.FeathersEventType.END_INTERACTION */ [Event(name="beginInteraction",type="starling.events.Event")] /** * Dispatched when the user stops dragging the content to open or close a * drawer. The drawer may continue opening or closing after this event is * dispatched if the user interaction has also triggered an animation. * *

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 * @see #event:beginInteraction feathers.events.FeathersEventType.BEGIN_INTERACTION */ [Event(name="endInteraction",type="starling.events.Event")] /** * Dispatched when a drawer has completed opening. The data * property of the event indicates which drawer is open. * *

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.
dataThe drawer that was opened.
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.OPEN * @see #event:close starling.events.Event.CLOSE */ [Event(name="open",type="starling.events.Event")] /** * Dispatched when a drawer has completed closing. The data * property of the event indicates which drawer was closed. * *

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.
dataThe drawer that was closed.
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.CLOSE * @see #event:open starling.events.Event.OPEN */ [Event(name="close",type="starling.events.Event")] /** * A container that displays primary content in the center surrounded by * optional "drawers" that can open and close on the edges. Useful for * mobile-style app menus that slide open from the side of the screen. * *

Additionally, each drawer may be individually "docked" in an * always-open state, making this a useful application-level layout * container even if the drawers never need to be hidden. Docking behavior * may be limited to either portrait or landscape, or a drawer may be docked * in both orientations. By default, a drawer is not docked.

* *

The following example creates an app with a slide out menu to the * left of the main content:

* * * var navigator:StackScreenNavigator = new StackScreenNavigator(); * var list:List = new List(); * // the navigator's screens, the list's data provider, and additional * // properties should be set here. * * var drawers:Drawers = new Drawers(); * drawers.content = navigator; * drawers.leftDrawer = menu; * drawers.leftDrawerToggleEventType = Event.OPEN; * this.addChild( drawers ); * *

In the example above, a screen in the StackScreenNavigator * component dispatches an event of type Event.OPEN when it * wants to display the slide out the List that is used as * the left drawer.

* * @see ../../../help/drawers.html How to use the Feathers Drawers component */ public class Drawers extends FeathersControl { /** * The default IStyleProvider for all Drawers * components. * * @default null * @see feathers.core.FeathersControl#styleProvider */ public static var globalStyleProvider:IStyleProvider; /** * The drawer will be docked in portrait orientation, but it must be * opened and closed explicitly in landscape orientation. * * @see #topDrawerDockMode * @see #rightDrawerDockMode * @see #bottomDrawerDockMode * @see #leftDrawerDockMode * @see #isTopDrawerDocked * @see #isRightDrawerDocked * @see #isBottomDrawerDocked * @see #isLeftDrawerDocked */ public static const DOCK_MODE_PORTRAIT:String = "portrait"; /** * The drawer will be docked in landscape orientation, but it must be * opened and closed explicitly in portrait orientation. * * @see #topDrawerDockMode * @see #rightDrawerDockMode * @see #bottomDrawerDockMode * @see #leftDrawerDockMode * @see #isTopDrawerDocked * @see #isRightDrawerDocked * @see #isBottomDrawerDocked * @see #isLeftDrawerDocked */ public static const DOCK_MODE_LANDSCAPE:String = "landscape"; /** * The drawer will be docked in all orientations. * * @see #topDrawerDockMode * @see #rightDrawerDockMode * @see #bottomDrawerDockMode * @see #leftDrawerDockMode * @see #isTopDrawerDocked * @see #isRightDrawerDocked * @see #isBottomDrawerDocked * @see #isLeftDrawerDocked */ public static const DOCK_MODE_BOTH:String = "both"; /** * The drawer won't be docked in any orientation. It must be opened and * closed explicitly in all orientations. * * @see #topDrawerDockMode * @see #rightDrawerDockMode * @see #bottomDrawerDockMode * @see #leftDrawerDockMode * @see #isTopDrawerDocked * @see #isRightDrawerDocked * @see #isBottomDrawerDocked * @see #isLeftDrawerDocked */ public static const DOCK_MODE_NONE:String = "none"; /** * The drawer will be displayed above the content. * * @see #openMode */ public static const OPEN_MODE_ABOVE:String = "overlay"; /** * The drawer will be displayed below the content. * * @see #openMode */ public static const OPEN_MODE_BELOW:String = "below"; /** * The drawers container will auto size itself to fill the entire stage. * * @see #autoSizeMode */ public static const AUTO_SIZE_MODE_STAGE:String = "stage"; /** * The drawers container will auto size itself to fit its content. * * @see #autoSizeMode */ public static const AUTO_SIZE_MODE_CONTENT:String = "content"; /** * A drawer will open by dragging the content starting from a certain * physical distance (in inches) from the nearest edge of the content. * To customize this distance, use the openGestureDragContentEdgeDistance * property. * * @see #openGesture * @see openGestureEdgeSize */ public static const OPEN_GESTURE_DRAG_CONTENT_EDGE:String = "dragContentEdge"; /** * A drawer will open by dragging the content from any location in the * appropriate direction. * * @see #openGesture */ public static const OPEN_GESTURE_DRAG_CONTENT:String = "dragContent"; /** * The drawers container will only open using the toggle event types * dispatched by the content. No gesture can be used to open a drawer. * * @see #openGesture * @see #topDrawerToggleEventType * @see #rightDrawerToggleEventType * @see #bottomDrawerToggleEventType * @see #leftDrawerToggleEventType */ public static const OPEN_GESTURE_NONE:String = "none"; /** * The field used to access the "content event dispatcher" of a * ScreenNavigator component, which happens to be the * currently active screen. * * @see #contentEventDispatcherField * @see feathers.controls.ScreenNavigator */ protected static const SCREEN_NAVIGATOR_CONTENT_EVENT_DISPATCHER_FIELD:String = "activeScreen"; /** * @private * The current velocity is given high importance. */ private static const CURRENT_VELOCITY_WEIGHT:Number = 2.33; /** * @private * Older saved velocities are given less importance. */ private static const VELOCITY_WEIGHTS:Vector. = new [1, 1.33, 1.66, 2]; /** * @private */ private static const MAXIMUM_SAVED_VELOCITY_COUNT:int = 4; /** * @private */ private static const HELPER_POINT:Point = new Point(); /** * Constructor. */ public function Drawers(content:IFeathersControl = null) { super(); this.content = content; this.addEventListener(Event.ADDED_TO_STAGE, drawers_addedToStageHandler); this.addEventListener(Event.REMOVED_FROM_STAGE, drawers_removedFromStageHandler); this.addEventListener(TouchEvent.TOUCH, drawers_touchHandler); } /** * The event dispatcher that controls opening and closing drawers with * events. Often, the event dispatcher is the content itself, but you * may specify a contentEventDispatcherField to access a * property of the content instead, or you may specify a * contentEventDispatcherFunction to run some more complex * code to access the event dispatcher. * * @see #contentEventDispatcherField * @see #contentEventDispatcherFunction */ protected var contentEventDispatcher:EventDispatcher; /** * @private */ override protected function get defaultStyleProvider():IStyleProvider { return Drawers.globalStyleProvider; } /** * @private */ protected var _originalContentWidth:Number = NaN; /** * @private */ protected var _originalContentHeight:Number = NaN; /** * @private */ protected var _content:IFeathersControl; /** * The primary content displayed in the center of the container. * *

If the primary content is a container where you'd prefer to listen * to events from its children, you may need to use properties like * contentEventDispatcherField, contentEventDispatcherFunction, * and contentEventDispatcherChangeEventType to ensure that * open and close events for drawers are correctly mapped to the correct * event dispatcher. If the content is dispatching the events, then those * properties should be set to null.

* *

In the following example, a StackScreenNavigator is added * as the content:

* * * var navigator:StackScreenNavigator = new StackScreenNavigator(); * // additional code to add the screens can go here * drawers.content = navigator; * * @default null * * @see #contentEventDispatcherField * @see #contentEventDispatcherFunction * @see #contentEventDispatcherChangeEventType */ public function get content():IFeathersControl { return this._content } /** * @private */ public function set content(value:IFeathersControl):void { if(this._content === value) { return; } if(this._content) { if(this._contentEventDispatcherChangeEventType) { this._content.removeEventListener(this._contentEventDispatcherChangeEventType, content_eventDispatcherChangeHandler); } this._content.removeEventListener(FeathersEventType.RESIZE, content_resizeHandler); if(this._content.parent === this) { this.removeChild(DisplayObject(this._content), false); } } this._content = value; this._originalContentWidth = NaN; this._originalContentHeight = NaN; if(this._content) { if(this._content is BaseScreenNavigator) { this.contentEventDispatcherField = SCREEN_NAVIGATOR_CONTENT_EVENT_DISPATCHER_FIELD; this.contentEventDispatcherChangeEventType = Event.CHANGE; } if(this._contentEventDispatcherChangeEventType) { this._content.addEventListener(this._contentEventDispatcherChangeEventType, content_eventDispatcherChangeHandler); } if(this._autoSizeMode === AUTO_SIZE_MODE_CONTENT || !this.stage) { this._content.addEventListener(FeathersEventType.RESIZE, content_resizeHandler); } if(this._openMode === OPEN_MODE_ABOVE) { this.addChildAt(DisplayObject(this._content), 0); } else //below { //the content should appear under the overlay skin, if it exists if(this._overlaySkin) { this.addChildAt(DisplayObject(this._content), this.getChildIndex(this._overlaySkin)); } else { this.addChild(DisplayObject(this._content)); } } } this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _overlaySkinOriginalAlpha:Number = 1; /** * @private */ protected var _overlaySkin:DisplayObject; /** * An optional display object that appears above the content when a * drawer is open. * *

In the following example, a Quad is added as the * overlay skin:

* * * var skin:Quad = new Quad( 10, 10, 0x000000 ); * skin.alpha = 0.75; * drawers.overlaySkin = skin; * * @default null */ public function get overlaySkin():DisplayObject { return this._overlaySkin } /** * @private */ public function set overlaySkin(value:DisplayObject):void { if(this._overlaySkin == value) { return; } if(this._overlaySkin && this._overlaySkin.parent == this) { this.removeChild(this._overlaySkin, false); } this._overlaySkin = value; if(this._overlaySkin) { this._overlaySkinOriginalAlpha = this._overlaySkin.alpha; this._overlaySkin.visible = this.isTopDrawerOpen || this.isRightDrawerOpen || this.isBottomDrawerOpen || this.isLeftDrawerOpen; this.addChild(this._overlaySkin); } this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _originalTopDrawerWidth:Number = NaN; /** * @private */ protected var _originalTopDrawerHeight:Number = NaN; /** * @private */ protected var _topDrawer:IFeathersControl; /** * The drawer that appears above the primary content. * *

In the following example, a List is added as the * top drawer:

* * * var list:List = new List(); * // set data provider and other properties here * drawers.topDrawer = list; * * @default null * * @see #topDrawerDockMode * @see #topDrawerToggleEventType */ public function get topDrawer():IFeathersControl { return this._topDrawer } /** * @private */ public function set topDrawer(value:IFeathersControl):void { if(this._topDrawer === value) { return; } if(this.isTopDrawerOpen && value === null) { this.isTopDrawerOpen = false; } if(this._topDrawer && this._topDrawer.parent === this) { this.removeChild(DisplayObject(this._topDrawer), false); } this._topDrawer = value; this._originalTopDrawerWidth = NaN; this._originalTopDrawerHeight = NaN; if(this._topDrawer) { this._topDrawer.visible = false; this._topDrawer.addEventListener(FeathersEventType.RESIZE, drawer_resizeHandler); if(this._openMode === OPEN_MODE_ABOVE) { this.addChild(DisplayObject(this._topDrawer)); } else //below { this.addChildAt(DisplayObject(this._topDrawer), 0); } } this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _topDrawerDivider:DisplayObject; /** * The divider between the top drawer and the content when the top * drawer is docked. * *

In the following example, a Quad is added as the * top drawer divider:

* * * var divider:Quad = new Quad( 2, 2, 0x999999 ); * drawers.topDrawerDivider = quad; * drawers.topDrawerDockMode = Drawers.DOCK_MODE_BOTH * * @default null * * @see #topDrawer */ public function get topDrawerDivider():DisplayObject { return this._topDrawerDivider; } /** * @private */ public function set topDrawerDivider(value:DisplayObject):void { if(this._topDrawerDivider === value) { return; } if(this._topDrawerDivider && this._topDrawerDivider.parent == this) { this.removeChild(this._topDrawerDivider, false); } this._topDrawerDivider = value; if(this._topDrawerDivider) { this._topDrawerDivider.visible = false; this.addChild(this._topDrawerDivider); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _topDrawerDockMode:String = DOCK_MODE_NONE; [Inspectable(type="String",enumeration="portrait,landscape,both,none")] /** * Determines if the top drawer is docked in all, some, or no stage * orientations. The current stage orientation is determined by * calculating the aspect ratio of the stage. * *

In the following example, the top drawer is docked in the * landscape stage orientation:

* * * drawers.topDrawerDockMode = Drawers.DOCK_MODE_LANDSCAPE; * * @default Drawers.DOCK_MODE_NONE * * @see #DOCK_MODE_PORTRAIT * @see #DOCK_MODE_LANDSCAPE * @see #DOCK_MODE_NONE * @see #DOCK_MODE_BOTH * @see #topDrawer */ public function get topDrawerDockMode():String { return this._topDrawerDockMode; } /** * @private */ public function set topDrawerDockMode(value:String):void { if(this._topDrawerDockMode == value) { return; } this._topDrawerDockMode = value; this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _topDrawerToggleEventType:String; /** * When this event is dispatched by the content event dispatcher, the * top drawer will toggle open and closed. * *

In the following example, the top drawer is toggled when the * content dispatches an event of type Event.OPEN:

* * * drawers.topDrawerToggleEventType = Event.OPEN; * * @default null * * @see #content * @see #topDrawer */ public function get topDrawerToggleEventType():String { return this._topDrawerToggleEventType; } /** * @private */ public function set topDrawerToggleEventType(value:String):void { if(this._topDrawerToggleEventType == value) { return; } if(this.contentEventDispatcher && this._topDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._topDrawerToggleEventType, content_topDrawerToggleEventTypeHandler); } this._topDrawerToggleEventType = value; if(this.contentEventDispatcher && this._topDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._topDrawerToggleEventType, content_topDrawerToggleEventTypeHandler); } } /** * @private */ protected var _isTopDrawerOpen:Boolean = false; /** * Indicates if the top drawer is currently open. If you want to check * if the top drawer is docked, check isTopDrawerDocked * instead. * *

To animate the top drawer open or closed, call * toggleTopDrawer(). Setting isTopDrawerOpen * will open or close the top drawer without animation.

* *

In the following example, we check if the top drawer is open:

* * * if( drawers.isTopDrawerOpen ) * { * // do something * } * * @default false * * @see #isTopDrawerDocked * @see #topDrawer * @see #toggleTopDrawer() */ public function get isTopDrawerOpen():Boolean { return this._topDrawer && this._isTopDrawerOpen; } /** * @private */ public function set isTopDrawerOpen(value:Boolean):void { if(this.isTopDrawerDocked || this._isTopDrawerOpen == value) { return; } this._isTopDrawerOpen = value; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Indicates if the top drawer is currently docked. Docking behavior of * the top drawer is controlled with the topDrawerDockMode * property. To check if the top drawer is open, but not docked, use * the isTopDrawerOpen property. * * @see #topDrawer * @see #topDrawerDockMode * @see #isTopDrawerOpen */ public function get isTopDrawerDocked():Boolean { if(!this._topDrawer) { return false; } if(this._topDrawerDockMode == DOCK_MODE_BOTH) { return true; } if(this._topDrawerDockMode == DOCK_MODE_NONE) { return false; } var stage:Stage = this.stage; if(!stage) { //fall back to the current stage, but it may be wrong... stage = Starling.current.stage; } if(stage.stageWidth > stage.stageHeight) { return this._topDrawerDockMode == DOCK_MODE_LANDSCAPE; } return this._topDrawerDockMode == DOCK_MODE_PORTRAIT; } /** * @private */ protected var _originalRightDrawerWidth:Number = NaN; /** * @private */ protected var _originalRightDrawerHeight:Number = NaN; /** * @private */ protected var _rightDrawer:IFeathersControl; /** * The drawer that appears to the right of the primary content. * *

In the following example, a List is added as the * right drawer:

* * * var list:List = new List(); * // set data provider and other properties here * drawers.rightDrawer = list; * * @default null * * @see #rightDrawerDockMode * @see #rightDrawerToggleEventType */ public function get rightDrawer():IFeathersControl { return this._rightDrawer } /** * @private */ public function set rightDrawer(value:IFeathersControl):void { if(this._rightDrawer == value) { return; } if(this.isRightDrawerOpen && value === null) { this.isRightDrawerOpen = false; } if(this._rightDrawer && this._rightDrawer.parent == this) { this.removeChild(DisplayObject(this._rightDrawer), false); } this._rightDrawer = value; this._originalRightDrawerWidth = NaN; this._originalRightDrawerHeight = NaN; if(this._rightDrawer) { this._rightDrawer.visible = false; this._rightDrawer.addEventListener(FeathersEventType.RESIZE, drawer_resizeHandler); if(this._openMode === OPEN_MODE_ABOVE) { this.addChild(DisplayObject(this._rightDrawer)); } else //below { this.addChildAt(DisplayObject(this._rightDrawer), 0); } } this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _rightDrawerDivider:DisplayObject; /** * The divider between the right drawer and the content when the right * drawer is docked. * *

In the following example, a Quad is added as the * right drawer divider:

* * * var divider:Quad = new Quad( 2, 2, 0x999999 ); * drawers.rightDrawerDivider = quad; * drawers.rightDrawerDockMode = Drawers.DOCK_MODE_BOTH * * @default null * * @see #rightDrawer */ public function get rightDrawerDivider():DisplayObject { return this._rightDrawerDivider; } /** * @private */ public function set rightDrawerDivider(value:DisplayObject):void { if(this._rightDrawerDivider === value) { return; } if(this._rightDrawerDivider && this._rightDrawerDivider.parent == this) { this.removeChild(this._rightDrawerDivider, false); } this._rightDrawerDivider = value; if(this._rightDrawerDivider) { this._rightDrawerDivider.visible = false; this.addChild(this._rightDrawerDivider); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _rightDrawerDockMode:String = DOCK_MODE_NONE; [Inspectable(type="String",enumeration="portrait,landscape,both,none")] /** * Determines if the right drawer is docked in all, some, or no stage * orientations. The current stage orientation is determined by * calculating the aspect ratio of the stage. * *

In the following example, the right drawer is docked in the * landscape stage orientation:

* * * drawers.rightDrawerDockMode = Drawers.DOCK_MODE_LANDSCAPE; * * @default Drawers.DOCK_MODE_NONE * * @see #DOCK_MODE_PORTRAIT * @see #DOCK_MODE_LANDSCAPE * @see #DOCK_MODE_NONE * @see #DOCK_MODE_BOTH * @see #rightDrawer */ public function get rightDrawerDockMode():String { return this._rightDrawerDockMode; } /** * @private */ public function set rightDrawerDockMode(value:String):void { if(this._rightDrawerDockMode == value) { return; } this._rightDrawerDockMode = value; this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _rightDrawerToggleEventType:String; /** * When this event is dispatched by the content event dispatcher, the * right drawer will toggle open and closed. * *

In the following example, the right drawer is toggled when the * content dispatches an event of type Event.OPEN:

* * * drawers.rightDrawerToggleEventType = Event.OPEN; * * @default null * * @see #content * @see #rightDrawer */ public function get rightDrawerToggleEventType():String { return this._rightDrawerToggleEventType; } /** * @private */ public function set rightDrawerToggleEventType(value:String):void { if(this._rightDrawerToggleEventType == value) { return; } if(this.contentEventDispatcher && this._rightDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._rightDrawerToggleEventType, content_rightDrawerToggleEventTypeHandler); } this._rightDrawerToggleEventType = value; if(this.contentEventDispatcher && this._rightDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._rightDrawerToggleEventType, content_rightDrawerToggleEventTypeHandler); } } /** * @private */ protected var _isRightDrawerOpen:Boolean = false; /** * Indicates if the right drawer is currently open. If you want to check * if the right drawer is docked, check isRightDrawerDocked * instead. * *

To animate the right drawer open or closed, call * toggleRightDrawer(). Setting isRightDrawerOpen * will open or close the right drawer without animation.

* *

In the following example, we check if the right drawer is open:

* * * if( drawers.isRightDrawerOpen ) * { * // do something * } * * @default false * * @see #rightDrawer * @see #rightDrawerDockMode * @see #toggleRightDrawer() */ public function get isRightDrawerOpen():Boolean { return this._rightDrawer && this._isRightDrawerOpen; } /** * @private */ public function set isRightDrawerOpen(value:Boolean):void { if(this.isRightDrawerDocked || this._isRightDrawerOpen == value) { return; } this._isRightDrawerOpen = value; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Indicates if the right drawer is currently docked. Docking behavior of * the right drawer is controlled with the rightDrawerDockMode * property. To check if the right drawer is open, but not docked, use * the isRightDrawerOpen property. * * @see #rightDrawer * @see #rightDrawerDockMode * @see #isRightDrawerOpen */ public function get isRightDrawerDocked():Boolean { if(!this._rightDrawer) { return false; } if(this._rightDrawerDockMode == DOCK_MODE_BOTH) { return true; } if(this._rightDrawerDockMode == DOCK_MODE_NONE) { return false; } var stage:Stage = this.stage; if(!stage) { //fall back to the current stage, but it may be wrong... stage = Starling.current.stage; } if(stage.stageWidth > stage.stageHeight) { return this._rightDrawerDockMode == DOCK_MODE_LANDSCAPE; } return this._rightDrawerDockMode == DOCK_MODE_PORTRAIT; } /** * @private */ protected var _originalBottomDrawerWidth:Number = NaN; /** * @private */ protected var _originalBottomDrawerHeight:Number = NaN; /** * @private */ protected var _bottomDrawer:IFeathersControl; /** * The drawer that appears below the primary content. * *

In the following example, a List is added as the * bottom drawer:

* * * var list:List = new List(); * // set data provider and other properties here * drawers.bottomDrawer = list; * * @default null * * @see #bottomDrawerDockMode * @see #bottomDrawerToggleEventType */ public function get bottomDrawer():IFeathersControl { return this._bottomDrawer } /** * @private */ public function set bottomDrawer(value:IFeathersControl):void { if(this._bottomDrawer === value) { return; } if(this.isBottomDrawerOpen && value === null) { this.isBottomDrawerOpen = false; } if(this._bottomDrawer && this._bottomDrawer.parent === this) { this.removeChild(DisplayObject(this._bottomDrawer), false); } this._bottomDrawer = value; this._originalBottomDrawerWidth = NaN; this._originalBottomDrawerHeight = NaN; if(this._bottomDrawer) { this._bottomDrawer.visible = false; this._bottomDrawer.addEventListener(FeathersEventType.RESIZE, drawer_resizeHandler); if(this._openMode === OPEN_MODE_ABOVE) { this.addChild(DisplayObject(this._bottomDrawer)); } else //below { this.addChildAt(DisplayObject(this._bottomDrawer), 0); } } this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _bottomDrawerDivider:DisplayObject; /** * The divider between the bottom drawer and the content when the bottom * drawer is docked. * *

In the following example, a Quad is added as the * bottom drawer divider:

* * * var divider:Quad = new Quad( 2, 2, 0x999999 ); * drawers.bottomDrawerDivider = quad; * drawers.bottomDrawerDockMode = Drawers.DOCK_MODE_BOTH * * @default null * * @see #bottomDrawer */ public function get bottomDrawerDivider():DisplayObject { return this._bottomDrawerDivider; } /** * @private */ public function set bottomDrawerDivider(value:DisplayObject):void { if(this._bottomDrawerDivider === value) { return; } if(this._bottomDrawerDivider && this._bottomDrawerDivider.parent == this) { this.removeChild(this._bottomDrawerDivider, false); } this._bottomDrawerDivider = value; if(this._bottomDrawerDivider) { this._bottomDrawerDivider.visible = false; this.addChild(this._bottomDrawerDivider); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _bottomDrawerDockMode:String = DOCK_MODE_NONE; [Inspectable(type="String",enumeration="portrait,landscape,both,none")] /** * Determines if the bottom drawer is docked in all, some, or no stage * orientations. The current stage orientation is determined by * calculating the aspect ratio of the stage. * *

In the following example, the bottom drawer is docked in the * landscape stage orientation:

* * * drawers.bottomDrawerDockMode = Drawers.DOCK_MODE_LANDSCAPE; * * @default Drawers.DOCK_MODE_NONE * * @see #DOCK_MODE_PORTRAIT * @see #DOCK_MODE_LANDSCAPE * @see #DOCK_MODE_NONE * @see #DOCK_MODE_BOTH * @see #bottomDrawer */ public function get bottomDrawerDockMode():String { return this._bottomDrawerDockMode; } /** * @private */ public function set bottomDrawerDockMode(value:String):void { if(this._bottomDrawerDockMode == value) { return; } this._bottomDrawerDockMode = value; this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _bottomDrawerToggleEventType:String; /** * When this event is dispatched by the content event dispatcher, the * bottom drawer will toggle open and closed. * *

In the following example, the bottom drawer is toggled when the * content dispatches an event of type Event.OPEN:

* * * drawers.bottomDrawerToggleEventType = Event.OPEN; * * @default null * * @see #content * @see #bottomDrawer */ public function get bottomDrawerToggleEventType():String { return this._bottomDrawerToggleEventType; } /** * @private */ public function set bottomDrawerToggleEventType(value:String):void { if(this._bottomDrawerToggleEventType == value) { return; } if(this.contentEventDispatcher && this._bottomDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._bottomDrawerToggleEventType, content_bottomDrawerToggleEventTypeHandler); } this._bottomDrawerToggleEventType = value; if(this.contentEventDispatcher && this._bottomDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._bottomDrawerToggleEventType, content_bottomDrawerToggleEventTypeHandler); } } /** * @private */ protected var _isBottomDrawerOpen:Boolean = false; /** * Indicates if the bottom drawer is currently open. If you want to check * if the bottom drawer is docked, check isBottomDrawerDocked * instead. * *

To animate the bottom drawer open or closed, call * toggleBottomDrawer(). Setting isBottomDrawerOpen * will open or close the bottom drawer without animation.

* *

In the following example, we check if the bottom drawer is open:

* * * if( drawers.isBottomDrawerOpen ) * { * // do something * } * * @default false * * @see #bottomDrawer * @see #isBottomDrawerOpen * @see #toggleBottomDrawer() */ public function get isBottomDrawerOpen():Boolean { return this._bottomDrawer && this._isBottomDrawerOpen; } /** * @private */ public function set isBottomDrawerOpen(value:Boolean):void { if(this.isBottomDrawerDocked || this._isBottomDrawerOpen == value) { return; } this._isBottomDrawerOpen = value; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Indicates if the bottom drawer is currently docked. Docking behavior of * the bottom drawer is controlled with the bottomDrawerDockMode * property. To check if the bottom drawer is open, but not docked, use * the isBottomDrawerOpen property. * * @see #bottomDrawer * @see #bottomDrawerDockMode * @see #isBottomDrawerOpen */ public function get isBottomDrawerDocked():Boolean { if(!this._bottomDrawer) { return false; } if(this._bottomDrawerDockMode == DOCK_MODE_BOTH) { return true; } if(this._bottomDrawerDockMode == DOCK_MODE_NONE) { return false; } var stage:Stage = this.stage; if(!stage) { //fall back to the current stage, but it may be wrong... stage = Starling.current.stage; } if(stage.stageWidth > stage.stageHeight) { return this._bottomDrawerDockMode == DOCK_MODE_LANDSCAPE; } return this._bottomDrawerDockMode == DOCK_MODE_PORTRAIT; } /** * @private */ protected var _originalLeftDrawerWidth:Number = NaN; /** * @private */ protected var _originalLeftDrawerHeight:Number = NaN; /** * @private */ protected var _leftDrawer:IFeathersControl; /** * The drawer that appears below the primary content. * *

In the following example, a List is added as the * left drawer:

* * * var list:List = new List(); * // set data provider and other properties here * drawers.leftDrawer = list; * * @default null * * @see #leftDrawerDockMode * @see #leftDrawerToggleEventType */ public function get leftDrawer():IFeathersControl { return this._leftDrawer; } /** * @private */ public function set leftDrawer(value:IFeathersControl):void { if(this._leftDrawer === value) { return; } if(this.isLeftDrawerOpen && value === null) { this.isLeftDrawerOpen = false; } if(this._leftDrawer && this._leftDrawer.parent === this) { this.removeChild(DisplayObject(this._leftDrawer), false); } this._leftDrawer = value; this._originalLeftDrawerWidth = NaN; this._originalLeftDrawerHeight = NaN; if(this._leftDrawer) { this._leftDrawer.visible = false; this._leftDrawer.addEventListener(FeathersEventType.RESIZE, drawer_resizeHandler); if(this._openMode === OPEN_MODE_ABOVE) { this.addChild(DisplayObject(this._leftDrawer)); } else //below { this.addChildAt(DisplayObject(this._leftDrawer), 0); } } this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _leftDrawerDivider:DisplayObject; /** * The divider between the left drawer and the content when the left * drawer is docked. * *

In the following example, a Quad is added as the * left drawer divider:

* * * var divider:Quad = new Quad( 2, 2, 0x999999 ); * drawers.leftDrawerDivider = quad; * drawers.leftDrawerDockMode = Drawers.DOCK_MODE_BOTH * * @default null * * @see #leftDrawer */ public function get leftDrawerDivider():DisplayObject { return this._leftDrawerDivider; } /** * @private */ public function set leftDrawerDivider(value:DisplayObject):void { if(this._leftDrawerDivider === value) { return; } if(this._leftDrawerDivider && this._leftDrawerDivider.parent == this) { this.removeChild(this._leftDrawerDivider, false); } this._leftDrawerDivider = value; if(this._leftDrawerDivider) { this._leftDrawerDivider.visible = false; this.addChild(this._leftDrawerDivider); } this.invalidate(INVALIDATION_FLAG_STYLES); } /** * @private */ protected var _leftDrawerDockMode:String = DOCK_MODE_NONE; [Inspectable(type="String",enumeration="portrait,landscape,both,none")] /** * Determines if the left drawer is docked in all, some, or no stage * orientations. The current stage orientation is determined by * calculating the aspect ratio of the stage. * *

In the following example, the left drawer is docked in the * landscape stage orientation:

* * * drawers.leftDrawerDockMode = Drawers.DOCK_MODE_LANDSCAPE; * * @default Drawers.DOCK_MODE_NONE * * @see #DOCK_MODE_PORTRAIT * @see #DOCK_MODE_LANDSCAPE * @see #DOCK_MODE_NONE * @see #DOCK_MODE_BOTH * @see #leftDrawer */ public function get leftDrawerDockMode():String { return this._leftDrawerDockMode; } /** * @private */ public function set leftDrawerDockMode(value:String):void { if(this._leftDrawerDockMode == value) { return; } this._leftDrawerDockMode = value; this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _leftDrawerToggleEventType:String; /** * When this event is dispatched by the content event dispatcher, the * left drawer will toggle open and closed. * *

In the following example, the left drawer is toggled when the * content dispatches and event of type Event.OPEN:

* * * drawers.leftDrawerToggleEventType = Event.OPEN; * * @default null * * @see #content * @see #leftDrawer */ public function get leftDrawerToggleEventType():String { return this._leftDrawerToggleEventType; } /** * @private */ public function set leftDrawerToggleEventType(value:String):void { if(this._leftDrawerToggleEventType == value) { return; } if(this.contentEventDispatcher && this._leftDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._leftDrawerToggleEventType, content_leftDrawerToggleEventTypeHandler); } this._leftDrawerToggleEventType = value; if(this.contentEventDispatcher && this._leftDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._leftDrawerToggleEventType, content_leftDrawerToggleEventTypeHandler); } } /** * @private */ protected var _isLeftDrawerOpen:Boolean = false; /** * Indicates if the left drawer is currently open. If you want to check * if the left drawer is docked, check isLeftDrawerDocked * instead. * *

To animate the left drawer open or closed, call * toggleLeftDrawer(). Setting isLeftDrawerOpen * will open or close the left drawer without animation.

* *

In the following example, we check if the left drawer is open:

* * * if( drawers.isLeftDrawerOpen ) * { * // do something * } * * @default false * * @see #leftDrawer * @see #isLeftDrawerDocked * @see #toggleLeftDrawer() */ public function get isLeftDrawerOpen():Boolean { return this._leftDrawer && this._isLeftDrawerOpen; } /** * @private */ public function set isLeftDrawerOpen(value:Boolean):void { if(this.isLeftDrawerDocked || this._isLeftDrawerOpen == value) { return; } this._isLeftDrawerOpen = value; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Indicates if the left drawer is currently docked. Docking behavior of * the left drawer is controlled with the leftDrawerDockMode * property. To check if the left drawer is open, but not docked, use * the isLeftDrawerOpen property. * * @see #leftDrawer * @see #leftDrawerDockMode * @see #isLeftDrawerOpen */ public function get isLeftDrawerDocked():Boolean { if(!this._leftDrawer) { return false; } if(this._leftDrawerDockMode == DOCK_MODE_BOTH) { return true; } if(this._leftDrawerDockMode == DOCK_MODE_NONE) { return false; } var stage:Stage = this.stage; if(!stage) { //fall back to the current stage, but it may be wrong... stage = Starling.current.stage; } if(stage.stageWidth > stage.stageHeight) { return this._leftDrawerDockMode == DOCK_MODE_LANDSCAPE; } return this._leftDrawerDockMode == DOCK_MODE_PORTRAIT; } /** * @private */ protected var _autoSizeMode:String = AUTO_SIZE_MODE_STAGE; [Inspectable(type="String",enumeration="stage,content")] /** * Determines how the drawers container will set its own size when its * dimensions (width and height) aren't set explicitly. * *

In the following example, the drawers container will be sized to * match its content:

* * * drawers.autoSizeMode = Drawers.AUTO_SIZE_MODE_CONTENT; * * @default Drawers.AUTO_SIZE_MODE_STAGE * * @see #AUTO_SIZE_MODE_STAGE * @see #AUTO_SIZE_MODE_CONTENT */ public function get autoSizeMode():String { return this._autoSizeMode; } /** * @private */ public function set autoSizeMode(value:String):void { if(this._autoSizeMode == value) { return; } this._autoSizeMode = value; if(this._content) { if(this._autoSizeMode == AUTO_SIZE_MODE_CONTENT) { this._content.addEventListener(FeathersEventType.RESIZE, content_resizeHandler); } else { this._content.removeEventListener(FeathersEventType.RESIZE, content_resizeHandler); } } this.invalidate(INVALIDATION_FLAG_SIZE); } /** * @private */ protected var _clipDrawers:Boolean = true; /** * Determines if the drawers are clipped while opening or closing. If * the content does not have a background, the drawers should * generally be clipped so that the drawer does not show under the * content. If the content has a fully opaque background that will * conceal the drawers, then clipping may be disabled to potentially * improve performance. * *

In the following example, clipping will be disabled:

* * * navigator.clipDrawers = false; * * @default true * * @see #topDrawer * @see #rightDrawer * @see #bottomDrawer * @see #leftDrawer */ public function get clipDrawers():Boolean { return this._clipDrawers; } /** * @private */ public function set clipDrawers(value:Boolean):void { if(this._clipDrawers == value) { return; } this._clipDrawers = value; this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _openMode:String = OPEN_MODE_BELOW; [Inspectable(type="String",enumeration="above,below")] /** * Determines whether the drawer opens above the content or below it. * *

In the following example, the drawers are opened above the * content:

* * * drawers.openMode = Drawers.OPEN_MODE_ABOVE; * * @default Drawers.OPEN_MODE_BELOW * * @see #OPEN_MODE_ABOVE * @see #OPEN_MODE_BELOW */ public function get openMode():String { return this._openMode; } /** * @private */ public function set openMode(value:String):void { if(this._openMode == value) { return; } this._openMode = value; if(this._content) { if(this._openMode === OPEN_MODE_ABOVE) { this.setChildIndex(DisplayObject(this._content), 0); } else //below { if(this._overlaySkin) { //the content should below the overlay skin this.setChildIndex(DisplayObject(this._content), this.numChildren - 1); this.setChildIndex(this._overlaySkin, this.numChildren - 1); } else { this.setChildIndex(DisplayObject(this._content), this.numChildren - 1); } } } this.invalidate(INVALIDATION_FLAG_LAYOUT); } /** * @private */ protected var _openGesture:String = OPEN_GESTURE_DRAG_CONTENT_EDGE; [Inspectable(type="String",enumeration="dragContentEdge,dragContent,none")] /** * An optional touch gesture used to open a drawer. * *

In the following example, the drawers are opened by dragging * anywhere inside the content:

* * * drawers.openGesture = Drawers.OPEN_GESTURE_DRAG_CONTENT; * * @default Drawers.OPEN_GESTURE_DRAG_CONTENT_EDGE * * @see #OPEN_GESTURE_NONE * @see #OPEN_GESTURE_DRAG_CONTENT * @see #OPEN_GESTURE_DRAG_CONTENT_EDGE */ public function get openGesture():String { return this._openGesture; } /** * @private */ public function set openGesture(value:String):void { this._openGesture = value; } /** * @private */ protected var _minimumDragDistance:Number = 0.04; /** * The minimum physical distance (in inches) that a touch must move * before a drag gesture begins. * *

In the following example, the minimum drag distance is customized:

* * * scroller.minimumDragDistance = 0.1; * * @default 0.04 */ public function get minimumDragDistance():Number { return this._minimumDragDistance; } /** * @private */ public function set minimumDragDistance(value:Number):void { this._minimumDragDistance = value; } /** * @private */ protected var _minimumDrawerThrowVelocity:Number = 5; /** * The minimum physical velocity (in inches per second) that a touch * must move before the a drawern can be "thrown" to open or close it. * Otherwise, it will settle open or closed based on which state is * closer when the touch ends. * *

In the following example, the minimum drawer throw velocity is customized:

* * * scroller.minimumDrawerThrowVelocity = 2; * * @default 5 */ public function get minimumDrawerThrowVelocity():Number { return this._minimumDrawerThrowVelocity; } /** * @private */ public function set minimumDrawerThrowVelocity(value:Number):void { this._minimumDrawerThrowVelocity = value; } /** * @private */ protected var _openGestureEdgeSize:Number = 0.1; /** * The minimum physical distance (in inches) that a touch must move * before a drag gesture begins. * *

In the following example, the open gesture edge size customized:

* * * scroller.openGestureEdgeSize = 0.25; * * @default 0.1 */ public function get openGestureEdgeSize():Number { return this._openGestureEdgeSize; } /** * @private */ public function set openGestureEdgeSize(value:Number):void { this._openGestureEdgeSize = value; } /** * @private */ protected var _contentEventDispatcherChangeEventType:String; /** * The event dispatched by the content to indicate that the content * event dispatcher has changed. When this event is dispatched by the * content, the drawers container will listen for the drawer toggle * events from the new dispatcher that discovered using * contentEventDispatcherField or * contentEventDispatcherFunction. * *

For StackScreenNavigator and * ScreenNavigator components, this value is automatically * set to Event.CHANGE.

* *

In the following example, the drawers container will update its * content event dispatcher when the content dispatches an event of type * Event.CHANGE:

* * * drawers.contentEventDispatcherChangeEventType = Event.CHANGE; * * @default null * * @see #contentEventDispatcherField * @see #contentEventDispatcherFunction */ public function get contentEventDispatcherChangeEventType():String { return this._contentEventDispatcherChangeEventType; } /** * @private */ public function set contentEventDispatcherChangeEventType(value:String):void { if(this._contentEventDispatcherChangeEventType == value) { return; } if(this._content && this._contentEventDispatcherChangeEventType) { this._content.removeEventListener(this._contentEventDispatcherChangeEventType, content_eventDispatcherChangeHandler); } this._contentEventDispatcherChangeEventType = value; if(this._content && this._contentEventDispatcherChangeEventType) { this._content.addEventListener(this._contentEventDispatcherChangeEventType, content_eventDispatcherChangeHandler); } } /** * @private */ protected var _contentEventDispatcherField:String; /** * A property of the content that references an event * dispatcher that dispatches events to toggle drawers open and closed. * *

For StackScreenNavigator and * ScreenNavigator components, this value is automatically * set to "activeScreen" to listen for events from the * currently active/visible screen.

* *

In the following example, the content event dispatcher field is * customized:

* * * drawers.contentEventDispatcherField = "selectedChild"; * * @default null * * @see #contentEventDispatcherFunction * @see #contentEventDispatcherChangeEventType * @see #topDrawerToggleEventType * @see #rightDrawerToggleEventType * @see #bottomDrawerToggleEventType * @see #leftDrawerToggleEventType */ public function get contentEventDispatcherField():String { return this._contentEventDispatcherField; } /** * @private */ public function set contentEventDispatcherField(value:String):void { if(this._contentEventDispatcherField == value) { return; } this._contentEventDispatcherField = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _contentEventDispatcherFunction:Function; /** * A function that returns an event dispatcher that dispatches events to * toggle drawers open and closed. * *

The function is expected to have the following signature:

* *
function( content:DisplayObject ):EventDispatcher
* *

In the following example, the content event dispatcher function is * customized:

* * * drawers.contentEventDispatcherField = function( content:CustomView ):void * { * return content.selectedChild; * }; * * @default null * * @see #contentEventDispatcherField * @see #contentEventDispatcherChangeEventType * @see #topDrawerToggleEventType * @see #rightDrawerToggleEventType * @see #bottomDrawerToggleEventType * @see #leftDrawerToggleEventType */ public function get contentEventDispatcherFunction():Function { return this._contentEventDispatcherFunction; } /** * @private */ public function set contentEventDispatcherFunction(value:Function):void { if(this._contentEventDispatcherFunction == value) { return; } this._contentEventDispatcherFunction = value; this.invalidate(INVALIDATION_FLAG_DATA); } /** * @private */ protected var _openOrCloseTween:Tween; /** * @private */ protected var _openOrCloseDuration:Number = 0.25; /** * The duration, in seconds, of the animation when a drawer opens or * closes. * *

In the following example, the duration of the animation that opens * or closes a drawer is set to 500 milliseconds:

* * * scroller.openOrCloseDuration = 0.5; * * @default 0.25 * * @see #openOrCloseEase */ public function get openOrCloseDuration():Number { return this._openOrCloseDuration; } /** * @private */ public function set openOrCloseDuration(value:Number):void { this._openOrCloseDuration = value; } /** * @private */ protected var _openOrCloseEase:Object = Transitions.EASE_OUT; /** * The easing function used for opening or closing the drawers. * *

In the following example, the ease of the animation that opens and * closes a drawer is customized:

* * * drawrs.openOrCloseEase = Transitions.EASE_IN_OUT; * * @default starling.animation.Transitions.EASE_OUT * * @see http://doc.starling-framework.org/core/starling/animation/Transitions.html starling.animation.Transitions * @see #openOrCloseDuration */ public function get openOrCloseEase():Object { return this._openOrCloseEase; } /** * @private */ public function set openOrCloseEase(value:Object):void { this._openOrCloseEase = value; } /** * @private */ protected var isToggleTopDrawerPending:Boolean = false; /** * @private */ protected var isToggleRightDrawerPending:Boolean = false; /** * @private */ protected var isToggleBottomDrawerPending:Boolean = false; /** * @private */ protected var isToggleLeftDrawerPending:Boolean = false; /** * @private */ protected var pendingToggleDuration:Number; /** * @private */ protected var touchPointID:int = -1; /** * @private */ protected var _isDragging:Boolean = false; /** * @private */ protected var _isDraggingTopDrawer:Boolean = false; /** * @private */ protected var _isDraggingRightDrawer:Boolean = false; /** * @private */ protected var _isDraggingBottomDrawer:Boolean = false; /** * @private */ protected var _isDraggingLeftDrawer:Boolean = false; /** * @private */ protected var _startTouchX:Number; /** * @private */ protected var _startTouchY:Number; /** * @private */ protected var _currentTouchX:Number; /** * @private */ protected var _currentTouchY:Number; /** * @private */ protected var _previousTouchTime:int; /** * @private */ protected var _previousTouchX:Number; /** * @private */ protected var _previousTouchY:Number; /** * @private */ protected var _velocityX:Number = 0; /** * @private */ protected var _velocityY:Number = 0; /** * @private */ protected var _previousVelocityX:Vector. = new []; /** * @private */ protected var _previousVelocityY:Vector. = new []; /** * @private */ override public function hitTest(localPoint:Point):DisplayObject { var result:DisplayObject = super.hitTest(localPoint); if(result) { if(this._isDragging) { return this; } if(this.isTopDrawerOpen && result != this._topDrawer && !(this._topDrawer is DisplayObjectContainer && DisplayObjectContainer(this._topDrawer).contains(result))) { return this; } else if(this.isRightDrawerOpen && result != this._rightDrawer && !(this._rightDrawer is DisplayObjectContainer && DisplayObjectContainer(this._rightDrawer).contains(result))) { return this; } else if(this.isBottomDrawerOpen && result != this._bottomDrawer && !(this._bottomDrawer is DisplayObjectContainer && DisplayObjectContainer(this._bottomDrawer).contains(result))) { return this; } else if(this.isLeftDrawerOpen && result != this._leftDrawer && !(this._leftDrawer is DisplayObjectContainer && DisplayObjectContainer(this._leftDrawer).contains(result))) { return this; } return result; } //we want to register touches in our hitArea as a last resort if(!this.visible || !this.touchable) { return null; } return this._hitArea.contains(localPoint.x, localPoint.y) ? this : null; } /** * Opens or closes the top drawer. If the duration argument * is NaN, the default openOrCloseDuration is * used. The default value of the duration argument is * NaN. Otherwise, this value is the duration of the * animation, in seconds. * *

To open or close the top drawer without animation, set the * isTopDrawerOpen property.

* * @see #isTopDrawerOpen * @see #openOrCloseDuration * @see #openOrCloseEase */ public function toggleTopDrawer(duration:Number = NaN):void { if(!this._topDrawer || this.isTopDrawerDocked) { return; } this.pendingToggleDuration = duration; if(this.isToggleTopDrawerPending) { return; } this.isToggleTopDrawerPending = true; this.isToggleRightDrawerPending = false; this.isToggleBottomDrawerPending = false; this.isToggleLeftDrawerPending = false; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Opens or closes the right drawer. If the duration argument * is NaN, the default openOrCloseDuration is * used. The default value of the duration argument is * NaN. Otherwise, this value is the duration of the * animation, in seconds. * *

To open or close the right drawer without animation, set the * isRightDrawerOpen property.

* * @see #isRightDrawerOpen * @see #openOrCloseDuration * @see #openOrCloseEase */ public function toggleRightDrawer(duration:Number = NaN):void { if(!this._rightDrawer || this.isRightDrawerDocked) { return; } this.pendingToggleDuration = duration; if(this.isToggleRightDrawerPending) { return; } this.isToggleTopDrawerPending = false; this.isToggleRightDrawerPending = true; this.isToggleBottomDrawerPending = false; this.isToggleLeftDrawerPending = false; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Opens or closes the bottom drawer. If the duration argument * is NaN, the default openOrCloseDuration is * used. The default value of the duration argument is * NaN. Otherwise, this value is the duration of the * animation, in seconds. * *

To open or close the bottom drawer without animation, set the * isBottomDrawerOpen property.

* * @see #isBottomDrawerOpen * @see #openOrCloseDuration * @see #openOrCloseEase */ public function toggleBottomDrawer(duration:Number = NaN):void { if(!this._bottomDrawer || this.isBottomDrawerDocked) { return; } this.pendingToggleDuration = duration; if(this.isToggleBottomDrawerPending) { return; } this.isToggleTopDrawerPending = false; this.isToggleRightDrawerPending = false; this.isToggleBottomDrawerPending = true; this.isToggleLeftDrawerPending = false; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * Opens or closes the left drawer. If the duration argument * is NaN, the default openOrCloseDuration is * used. The default value of the duration argument is * NaN. Otherwise, this value is the duration of the * animation, in seconds. * *

To open or close the left drawer without animation, set the * isLeftDrawerOpen property.

* * @see #isLeftDrawerOpen * @see #openOrCloseDuration * @see #openOrCloseEase */ public function toggleLeftDrawer(duration:Number = NaN):void { if(!this._leftDrawer || this.isLeftDrawerDocked) { return; } this.pendingToggleDuration = duration; if(this.isToggleLeftDrawerPending) { return; } this.isToggleTopDrawerPending = false; this.isToggleRightDrawerPending = false; this.isToggleBottomDrawerPending = false; this.isToggleLeftDrawerPending = true; this.invalidate(INVALIDATION_FLAG_SELECTED); } /** * @private */ override protected function draw():void { var sizeInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SIZE); var dataInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_DATA); var layoutInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_LAYOUT); var selectedInvalid:Boolean = this.isInvalid(INVALIDATION_FLAG_SELECTED); if(dataInvalid) { this.refreshCurrentEventTarget(); } if(sizeInvalid || layoutInvalid) { this.refreshDrawerStates(); } if(layoutInvalid || selectedInvalid) { this.refreshOverlayState(); } sizeInvalid = this.autoSizeIfNeeded() || sizeInvalid; this.layoutChildren(); this.handlePendingActions(); } /** * 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 { var needsWidth:Boolean = this._explicitWidth !== this._explicitWidth; //isNaN var needsHeight:Boolean = this._explicitHeight !== this._explicitHeight; //isNaN var needsMinWidth:Boolean = this._explicitMinWidth !== this._explicitMinWidth; //isNaN var needsMinHeight:Boolean = this._explicitMinHeight !== this._explicitMinHeight; //isNaN if(!needsWidth && !needsHeight && !needsMinWidth && !needsMinHeight) { return false; } var measureContent:Boolean = this._autoSizeMode === AUTO_SIZE_MODE_CONTENT || !this.stage; var isTopDrawerDocked:Boolean = this.isTopDrawerDocked; var isRightDrawerDocked:Boolean = this.isRightDrawerDocked; var isBottomDrawerDocked:Boolean = this.isBottomDrawerDocked; var isLeftDrawerDocked:Boolean = this.isLeftDrawerDocked; if(measureContent) { if(this._content) { this._content.validate(); if(this._originalContentWidth !== this._originalContentWidth) //isNaN { this._originalContentWidth = this._content.width; } if(this._originalContentHeight !== this._originalContentHeight) //isNaN { this._originalContentHeight = this._content.height; } } if(isTopDrawerDocked) { this._topDrawer.validate(); if(this._originalTopDrawerWidth !== this._originalTopDrawerWidth) //isNaN { this._originalTopDrawerWidth = this._topDrawer.width; } if(this._originalTopDrawerHeight !== this._originalTopDrawerHeight) //isNaN { this._originalTopDrawerHeight = this._topDrawer.height; } } if(isRightDrawerDocked) { this._rightDrawer.validate(); if(this._originalRightDrawerWidth !== this._originalRightDrawerWidth) //isNaN { this._originalRightDrawerWidth = this._rightDrawer.width; } if(this._originalRightDrawerHeight !== this._originalRightDrawerHeight) //isNaN { this._originalRightDrawerHeight = this._rightDrawer.height; } } if(isBottomDrawerDocked) { this._bottomDrawer.validate(); if(this._originalBottomDrawerWidth !== this._originalBottomDrawerWidth) //isNaN { this._originalBottomDrawerWidth = this._bottomDrawer.width; } if(this._originalBottomDrawerHeight !== this._originalBottomDrawerHeight) //isNaN { this._originalBottomDrawerHeight = this._bottomDrawer.height; } } if(isLeftDrawerDocked) { this._leftDrawer.validate(); if(this._originalLeftDrawerWidth !== this._originalLeftDrawerWidth) //isNaN { this._originalLeftDrawerWidth = this._leftDrawer.width; } if(this._originalLeftDrawerHeight !== this._originalLeftDrawerHeight) //isNaN { this._originalLeftDrawerHeight = this._leftDrawer.height; } } } var newWidth:Number = this._explicitWidth; if(needsWidth) { if(measureContent) { if(this._content) { newWidth = this._originalContentWidth; } else { newWidth = 0; } if(isLeftDrawerDocked) { newWidth += this._originalLeftDrawerWidth; } if(isRightDrawerDocked) { newWidth += this._originalRightDrawerWidth; } if(isTopDrawerDocked && this._originalTopDrawerWidth > newWidth) { newWidth = this._originalTopDrawerWidth; } if(isBottomDrawerDocked && this._originalBottomDrawerWidth > newWidth) { newWidth = this._originalBottomDrawerWidth; } } else { newWidth = this.stage.stageWidth; } } var newHeight:Number = this._explicitHeight; if(needsHeight) { if(measureContent) { if(this._content) { newHeight = this._originalContentHeight; } else { newHeight = 0; } if(isTopDrawerDocked) { newHeight += this._originalTopDrawerHeight; } if(isBottomDrawerDocked) { newHeight += this._originalBottomDrawerHeight; } if(isLeftDrawerDocked && this._originalLeftDrawerHeight > newHeight) { newHeight = this._originalLeftDrawerHeight; } if(isRightDrawerDocked && this._originalRightDrawerHeight > newHeight) { newHeight = this._originalRightDrawerHeight; } } else { newHeight = this.stage.stageHeight; } } var newMinWidth:Number = this._explicitMinWidth; if(needsMinWidth) { if(measureContent) { newMinWidth = this._content.minWidth; if(isLeftDrawerDocked) { newMinWidth += this._leftDrawer.minWidth; } if(isRightDrawerDocked) { newMinWidth += this._rightDrawer.minWidth; } if(isTopDrawerDocked && this._topDrawer.minWidth > newMinWidth) { newMinWidth = this._topDrawer.minWidth; } if(isBottomDrawerDocked && this._bottomDrawer.minWidth > newMinWidth) { newMinWidth = this._bottomDrawer.minWidth; } } else { newMinWidth = this.stage.stageWidth; } } var newMinHeight:Number = this._explicitMinHeight; if(needsMinHeight) { if(measureContent) { newMinHeight = this._content.minHeight; if(isTopDrawerDocked) { newMinHeight += this._topDrawer.minHeight; } if(isBottomDrawerDocked) { newMinHeight += this._bottomDrawer.minHeight; } if(isLeftDrawerDocked && this._leftDrawer.minHeight > newMinHeight) { newMinHeight = this._leftDrawer.minHeight; } if(isRightDrawerDocked && this._rightDrawer.minHeight > newMinHeight) { newMinHeight = this._rightDrawer.minHeight; } } else { newMinHeight = this.stage.stageHeight; } } return this.saveMeasurements(newWidth, newHeight, newMinWidth, newMinHeight); } /** * Positions and sizes the children. */ protected function layoutChildren():void { if(this._topDrawer) { this._topDrawer.validate(); } if(this._rightDrawer) { this._rightDrawer.validate(); } if(this._bottomDrawer) { this._bottomDrawer.validate(); } if(this._leftDrawer) { this._leftDrawer.validate(); } if(this._topDrawerDivider is IValidating) { IValidating(this._topDrawerDivider).validate(); } if(this._rightDrawerDivider is IValidating) { IValidating(this._rightDrawerDivider).validate(); } if(this._bottomDrawerDivider is IValidating) { IValidating(this._bottomDrawerDivider).validate(); } if(this._leftDrawerDivider is IValidating) { IValidating(this._leftDrawerDivider).validate(); } var isTopDrawerOpen:Boolean = this.isTopDrawerOpen; var isRightDrawerOpen:Boolean = this.isRightDrawerOpen; var isBottomDrawerOpen:Boolean = this.isBottomDrawerOpen; var isLeftDrawerOpen:Boolean = this.isLeftDrawerOpen; var isTopDrawerDocked:Boolean = this.isTopDrawerDocked; var isRightDrawerDocked:Boolean = this.isRightDrawerDocked; var isBottomDrawerDocked:Boolean = this.isBottomDrawerDocked; var isLeftDrawerDocked:Boolean = this.isLeftDrawerDocked; var topDrawerHeight:Number = this._topDrawer ? this._topDrawer.height : 0; var rightDrawerWidth:Number = this._rightDrawer ? this._rightDrawer.width : 0; var bottomDrawerHeight:Number = this._bottomDrawer ? this._bottomDrawer.height : 0; var leftDrawerWidth:Number = this._leftDrawer ? this._leftDrawer.width : 0; var contentWidth:Number = this.actualWidth; if(isLeftDrawerDocked) { contentWidth -= leftDrawerWidth; if(this._leftDrawerDivider) { contentWidth -= this._leftDrawerDivider.width; } } if(isRightDrawerDocked) { contentWidth -= rightDrawerWidth; if(this._rightDrawerDivider) { contentWidth -= this._rightDrawerDivider.width; } } var contentHeight:Number = this.actualHeight; if(isTopDrawerDocked) { contentHeight -= topDrawerHeight; if(this._topDrawerDivider) { contentHeight -= this._topDrawerDivider.height; } } if(isBottomDrawerDocked) { contentHeight -= bottomDrawerHeight; if(this._bottomDrawerDivider) { contentHeight -= this._bottomDrawerDivider.height; } } var contentX:Number = 0; if(isRightDrawerOpen && this._openMode === OPEN_MODE_BELOW) { contentX = -rightDrawerWidth; if(isLeftDrawerDocked) { contentX += leftDrawerWidth; if(this._leftDrawerDivider) { contentX += this._leftDrawerDivider.width; } } } else if((isLeftDrawerOpen && this._openMode === OPEN_MODE_BELOW) || isLeftDrawerDocked) { contentX = leftDrawerWidth; if(this._leftDrawerDivider && isLeftDrawerDocked) { contentX += this._leftDrawerDivider.width; } } this._content.x = contentX; var contentY:Number = 0; if(isBottomDrawerOpen && this._openMode === OPEN_MODE_BELOW) { contentY = -bottomDrawerHeight; if(isTopDrawerDocked) { contentY += topDrawerHeight; if(this._topDrawerDivider) { contentY += this._topDrawerDivider.height; } } } else if((isTopDrawerOpen && this._openMode === OPEN_MODE_BELOW) || isTopDrawerDocked) { contentY = topDrawerHeight; if(this._topDrawerDivider && isTopDrawerDocked) { contentY += this._topDrawerDivider.height; } } this._content.y = contentY; if(this._autoSizeMode !== AUTO_SIZE_MODE_CONTENT) { this._content.width = contentWidth; this._content.height = contentHeight; //final validation to avoid juggler next frame issues this._content.validate(); } if(this._topDrawer) { var topDrawerX:Number = 0; var topDrawerY:Number = 0; if(isTopDrawerDocked) { if(isBottomDrawerOpen && this._openMode === OPEN_MODE_BELOW) { topDrawerY -= bottomDrawerHeight; } if(!isLeftDrawerDocked) { topDrawerX = this._content.x; } } else if(this._openMode === OPEN_MODE_ABOVE && !this._isTopDrawerOpen) { topDrawerY -= topDrawerHeight; } this._topDrawer.x = topDrawerX; this._topDrawer.y = topDrawerY; this._topDrawer.width = this.actualWidth; this._topDrawer.visible = isTopDrawerOpen || isTopDrawerDocked || this._isDraggingTopDrawer; if(this._topDrawerDivider) { this._topDrawerDivider.visible = isTopDrawerDocked; this._topDrawerDivider.x = topDrawerX; this._topDrawerDivider.y = topDrawerY + topDrawerHeight; this._topDrawerDivider.width = this.actualWidth; } //final validation to avoid juggler next frame issues this._topDrawer.validate(); } if(this._rightDrawer) { var rightDrawerX:Number = this.actualWidth - rightDrawerWidth; var rightDrawerY:Number = 0; var rightDrawerHeight:Number = this.actualHeight; if(isRightDrawerDocked) { rightDrawerX = this._content.x + this._content.width; if(this._rightDrawerDivider) { rightDrawerX += this._rightDrawerDivider.width; } if(isTopDrawerDocked) { rightDrawerHeight -= topDrawerHeight; } if(isBottomDrawerDocked) { rightDrawerHeight -= bottomDrawerHeight; } rightDrawerY = this._content.y; } else if(this._openMode === OPEN_MODE_ABOVE && !this._isRightDrawerOpen) { rightDrawerX += rightDrawerWidth; } this._rightDrawer.x = rightDrawerX; this._rightDrawer.y = rightDrawerY; this._rightDrawer.height = rightDrawerHeight; this._rightDrawer.visible = isRightDrawerOpen || isRightDrawerDocked || this._isDraggingRightDrawer; if(this._rightDrawerDivider) { this._rightDrawerDivider.visible = isRightDrawerDocked; this._rightDrawerDivider.x = rightDrawerX - this._rightDrawerDivider.width; this._rightDrawerDivider.y = rightDrawerY; this._rightDrawerDivider.height = rightDrawerHeight; } //final validation to avoid juggler next frame issues this._rightDrawer.validate(); } if(this._bottomDrawer) { var bottomDrawerX:Number = 0; var bottomDrawerY:Number = this.actualHeight - bottomDrawerHeight; if(isBottomDrawerDocked) { if(!isLeftDrawerDocked) { bottomDrawerX = this._content.x; } bottomDrawerY = this._content.y + this._content.height; if(this._bottomDrawerDivider) { bottomDrawerY += this._bottomDrawerDivider.height; } } else if(this._openMode === OPEN_MODE_ABOVE && !this._isBottomDrawerOpen) { bottomDrawerY += bottomDrawerHeight; } this._bottomDrawer.x = bottomDrawerX; this._bottomDrawer.y = bottomDrawerY; this._bottomDrawer.width = this.actualWidth; this._bottomDrawer.visible = isBottomDrawerOpen || isBottomDrawerDocked || this._isDraggingBottomDrawer; if(this._bottomDrawerDivider) { this._bottomDrawerDivider.visible = isBottomDrawerDocked; this._bottomDrawerDivider.x = bottomDrawerX; this._bottomDrawerDivider.y = bottomDrawerY - this._bottomDrawerDivider.height; this._bottomDrawerDivider.width = this.actualWidth; } //final validation to avoid juggler next frame issues this._bottomDrawer.validate(); } if(this._leftDrawer) { var leftDrawerX:Number = 0; var leftDrawerY:Number = 0; var leftDrawerHeight:Number = this.actualHeight; if(isLeftDrawerDocked) { if(isRightDrawerOpen && this._openMode === OPEN_MODE_BELOW) { leftDrawerX -= rightDrawerWidth; } if(isTopDrawerDocked) { leftDrawerHeight -= topDrawerHeight; } if(isBottomDrawerDocked) { leftDrawerHeight -= bottomDrawerHeight; } leftDrawerY = this._content.y; } else if(this._openMode === OPEN_MODE_ABOVE && !this._isLeftDrawerOpen) { leftDrawerX -= leftDrawerWidth; } this._leftDrawer.x = leftDrawerX; this._leftDrawer.y = leftDrawerY; this._leftDrawer.height = leftDrawerHeight; this._leftDrawer.visible = isLeftDrawerOpen || isLeftDrawerDocked || this._isDraggingLeftDrawer; if(this._leftDrawerDivider) { this._leftDrawerDivider.visible = isLeftDrawerDocked; this._leftDrawerDivider.x = leftDrawerX + leftDrawerWidth; this._leftDrawerDivider.y = leftDrawerY; this._leftDrawerDivider.height = leftDrawerHeight; } //final validation to avoid juggler next frame issues this._leftDrawer.validate(); } if(this._overlaySkin) { this.positionOverlaySkin(); this._overlaySkin.width = this.actualWidth; this._overlaySkin.height = this.actualHeight; //final validation to avoid juggler next frame issues if(this._overlaySkin is IValidating) { IValidating(this._overlaySkin).validate(); } } } /** * @private */ protected function handlePendingActions():void { if(this.isToggleTopDrawerPending) { this._isTopDrawerOpen = !this._isTopDrawerOpen; this.isToggleTopDrawerPending = false; this.openOrCloseTopDrawer(); } else if(this.isToggleRightDrawerPending) { this._isRightDrawerOpen = !this._isRightDrawerOpen; this.isToggleRightDrawerPending = false; this.openOrCloseRightDrawer(); } else if(this.isToggleBottomDrawerPending) { this._isBottomDrawerOpen = !this._isBottomDrawerOpen; this.isToggleBottomDrawerPending = false; this.openOrCloseBottomDrawer(); } else if(this.isToggleLeftDrawerPending) { this._isLeftDrawerOpen = !this._isLeftDrawerOpen; this.isToggleLeftDrawerPending = false; this.openOrCloseLeftDrawer(); } } /** * @private */ protected function openOrCloseTopDrawer():void { if(!this._topDrawer || this.isTopDrawerDocked) { return; } if(this._openOrCloseTween) { this._openOrCloseTween.advanceTime(this._openOrCloseTween.totalTime); Starling.juggler.remove(this._openOrCloseTween); this._openOrCloseTween = null; } this.prepareTopDrawer(); if(this._overlaySkin) { this._overlaySkin.visible = true; if(this._isTopDrawerOpen) { this._overlaySkin.alpha = 0; } else { this._overlaySkin.alpha = this._overlaySkinOriginalAlpha; } } var targetPosition:Number = this._isTopDrawerOpen ? this._topDrawer.height : 0; var duration:Number = this.pendingToggleDuration; if(duration !== duration) //isNaN { duration = this._openOrCloseDuration; } this.pendingToggleDuration = NaN; if(this._openMode === OPEN_MODE_ABOVE) { targetPosition = targetPosition === 0 ? -this._topDrawer.height : 0; this._openOrCloseTween = new Tween(this._topDrawer, duration, this._openOrCloseEase); } else //below { this._openOrCloseTween = new Tween(this._content, duration, this._openOrCloseEase); } this._openOrCloseTween.animate("y", targetPosition); this._openOrCloseTween.onUpdate = topDrawerOpenOrCloseTween_onUpdate; this._openOrCloseTween.onComplete = topDrawerOpenOrCloseTween_onComplete; Starling.juggler.add(this._openOrCloseTween); } /** * @private */ protected function openOrCloseRightDrawer():void { if(!this._rightDrawer || this.isRightDrawerDocked) { return; } if(this._openOrCloseTween) { this._openOrCloseTween.advanceTime(this._openOrCloseTween.totalTime); Starling.juggler.remove(this._openOrCloseTween); this._openOrCloseTween = null; } this.prepareRightDrawer(); if(this._overlaySkin) { this._overlaySkin.visible = true; if(this._isRightDrawerOpen) { this._overlaySkin.alpha = 0; } else { this._overlaySkin.alpha = this._overlaySkinOriginalAlpha; } } var targetPosition:Number = 0; if(this._isRightDrawerOpen) { targetPosition = -this._rightDrawer.width; } if(this.isLeftDrawerDocked && this._openMode === OPEN_MODE_BELOW) { targetPosition += this._leftDrawer.width; if(this._leftDrawerDivider) { targetPosition += this._leftDrawerDivider.width; } } var duration:Number = this.pendingToggleDuration; if(duration !== duration) //isNaN { duration = this._openOrCloseDuration; } this.pendingToggleDuration = NaN; if(this._openMode === OPEN_MODE_ABOVE) { this._openOrCloseTween = new Tween(this._rightDrawer, duration, this._openOrCloseEase); targetPosition += this.actualWidth; } else //below { this._openOrCloseTween = new Tween(this._content, duration, this._openOrCloseEase); } this._openOrCloseTween.animate("x", targetPosition); this._openOrCloseTween.onUpdate = rightDrawerOpenOrCloseTween_onUpdate; this._openOrCloseTween.onComplete = rightDrawerOpenOrCloseTween_onComplete; Starling.juggler.add(this._openOrCloseTween); } /** * @private */ protected function openOrCloseBottomDrawer():void { if(!this._bottomDrawer || this.isBottomDrawerDocked) { return; } if(this._openOrCloseTween) { this._openOrCloseTween.advanceTime(this._openOrCloseTween.totalTime); Starling.juggler.remove(this._openOrCloseTween); this._openOrCloseTween = null; } this.prepareBottomDrawer(); if(this._overlaySkin) { this._overlaySkin.visible = true; if(this._isBottomDrawerOpen) { this._overlaySkin.alpha = 0; } else { this._overlaySkin.alpha = this._overlaySkinOriginalAlpha; } } var targetPosition:Number = 0; if(this._isBottomDrawerOpen) { targetPosition = -this._bottomDrawer.height; } if(this.isTopDrawerDocked && this._openMode === OPEN_MODE_BELOW) { targetPosition += this._topDrawer.height; if(this._topDrawerDivider) { targetPosition += this._topDrawerDivider.height; } } var duration:Number = this.pendingToggleDuration; if(duration !== duration) //isNaN { duration = this._openOrCloseDuration; } this.pendingToggleDuration = NaN; if(this._openMode === OPEN_MODE_ABOVE) { targetPosition += this.actualHeight; this._openOrCloseTween = new Tween(this._bottomDrawer, duration, this._openOrCloseEase); } else //below { this._openOrCloseTween = new Tween(this._content, duration, this._openOrCloseEase); } this._openOrCloseTween.animate("y", targetPosition); this._openOrCloseTween.onUpdate = bottomDrawerOpenOrCloseTween_onUpdate; this._openOrCloseTween.onComplete = bottomDrawerOpenOrCloseTween_onComplete; Starling.juggler.add(this._openOrCloseTween); } /** * @private */ protected function openOrCloseLeftDrawer():void { if(!this._leftDrawer || this.isLeftDrawerDocked) { return; } if(this._openOrCloseTween) { this._openOrCloseTween.advanceTime(this._openOrCloseTween.totalTime); Starling.juggler.remove(this._openOrCloseTween); this._openOrCloseTween = null; } this.prepareLeftDrawer(); if(this._overlaySkin) { this._overlaySkin.visible = true; if(this._isLeftDrawerOpen) { this._overlaySkin.alpha = 0; } else { this._overlaySkin.alpha = this._overlaySkinOriginalAlpha; } } var targetPosition:Number = this._isLeftDrawerOpen ? this._leftDrawer.width : 0; var duration:Number = this.pendingToggleDuration; if(duration !== duration) //isNaN { duration = this._openOrCloseDuration; } this.pendingToggleDuration = NaN; if(this._openMode === OPEN_MODE_ABOVE) { targetPosition = targetPosition === 0 ? -this._leftDrawer.width : 0; this._openOrCloseTween = new Tween(this._leftDrawer, duration, this._openOrCloseEase); } else //below { this._openOrCloseTween = new Tween(this._content, duration, this._openOrCloseEase); } this._openOrCloseTween.animate("x", targetPosition); this._openOrCloseTween.onUpdate = leftDrawerOpenOrCloseTween_onUpdate; this._openOrCloseTween.onComplete = leftDrawerOpenOrCloseTween_onComplete; Starling.juggler.add(this._openOrCloseTween); } /** * @private */ protected function prepareTopDrawer():void { this._topDrawer.visible = true; if(this._openMode === OPEN_MODE_ABOVE) { if(this._overlaySkin) { this.setChildIndex(this._overlaySkin, this.numChildren - 1); } this.setChildIndex(DisplayObject(this._topDrawer), this.numChildren - 1); } if(!this._clipDrawers || this._openMode !== OPEN_MODE_BELOW) { return; } if(this._topDrawer.mask === null) { var mask:Quad = new Quad(1, 1, 0xff00ff); //the initial dimensions cannot be 0 or there's a runtime error, //and these values might be 0 mask.width = this.actualWidth; mask.height = this._content.y; this._topDrawer.mask = mask; } } /** * @private */ protected function prepareRightDrawer():void { this._rightDrawer.visible = true; if(this._openMode === OPEN_MODE_ABOVE) { if(this._overlaySkin) { this.setChildIndex(this._overlaySkin, this.numChildren - 1); } this.setChildIndex(DisplayObject(this._rightDrawer), this.numChildren - 1); } if(!this._clipDrawers || this._openMode !== OPEN_MODE_BELOW) { return; } if(this._rightDrawer.mask === null) { var mask:Quad = new Quad(1, 1, 0xff00ff); //the initial dimensions cannot be 0 or there's a runtime error, //and these values might be 0 mask.width = -this._content.x; mask.height = this.actualHeight; this._rightDrawer.mask = mask; } } /** * @private */ protected function prepareBottomDrawer():void { this._bottomDrawer.visible = true; if(this._openMode === OPEN_MODE_ABOVE) { if(this._overlaySkin) { this.setChildIndex(this._overlaySkin, this.numChildren - 1); } this.setChildIndex(DisplayObject(this._bottomDrawer), this.numChildren - 1); } if(!this._clipDrawers || this._openMode !== OPEN_MODE_BELOW) { return; } if(this._bottomDrawer.mask === null) { var mask:Quad = new Quad(1, 1, 0xff00ff); //the initial dimensions cannot be 0 or there's a runtime error, //and these values might be 0 mask.width = this.actualWidth; mask.height = -this._content.y; this._bottomDrawer.mask = mask; } } /** * @private */ protected function prepareLeftDrawer():void { this._leftDrawer.visible = true; if(this._openMode === OPEN_MODE_ABOVE) { if(this._overlaySkin) { this.setChildIndex(this._overlaySkin, this.numChildren - 1); } this.setChildIndex(DisplayObject(this._leftDrawer), this.numChildren - 1); } if(!this._clipDrawers || this._openMode !== OPEN_MODE_BELOW) { return; } if(this._leftDrawer.mask === null) { var mask:Quad = new Quad(1, 1, 0xff00ff); //the initial dimensions cannot be 0 or there's a runtime error, //and these values might be 0 mask.width = this._content.x; mask.height = this.actualHeight; this._leftDrawer.mask = mask; } } /** * Uses the content event dispatcher fields and functions to generate a * content event dispatcher icon for the content. * *

All of the content event dispatcher fields and functions, ordered * by priority:

*
    *
  1. contentEventDispatcherFunction
  2. *
  3. contentEventDispatcherField
  4. *
* * @see #content * @see #contentEventDispatcherField * @see #contentEventDispatcherFunction * @see #contentEventDispatcherChangeEventType */ protected function contentToContentEventDispatcher():EventDispatcher { if(this._contentEventDispatcherFunction !== null) { return this._contentEventDispatcherFunction(this._content) as EventDispatcher; } else if(this._contentEventDispatcherField !== null && this._content && (this._contentEventDispatcherField in this._content)) { return this._content[this._contentEventDispatcherField] as EventDispatcher; } return this._content as EventDispatcher; } /** * @private */ protected function refreshCurrentEventTarget():void { if(this.contentEventDispatcher) { if(this._topDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._topDrawerToggleEventType, content_topDrawerToggleEventTypeHandler); } if(this._rightDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._rightDrawerToggleEventType, content_rightDrawerToggleEventTypeHandler); } if(this._bottomDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._bottomDrawerToggleEventType, content_bottomDrawerToggleEventTypeHandler); } if(this._leftDrawerToggleEventType) { this.contentEventDispatcher.removeEventListener(this._leftDrawerToggleEventType, content_leftDrawerToggleEventTypeHandler); } } this.contentEventDispatcher = this.contentToContentEventDispatcher(); if(this.contentEventDispatcher) { if(this._topDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._topDrawerToggleEventType, content_topDrawerToggleEventTypeHandler); } if(this._rightDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._rightDrawerToggleEventType, content_rightDrawerToggleEventTypeHandler); } if(this._bottomDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._bottomDrawerToggleEventType, content_bottomDrawerToggleEventTypeHandler); } if(this._leftDrawerToggleEventType) { this.contentEventDispatcher.addEventListener(this._leftDrawerToggleEventType, content_leftDrawerToggleEventTypeHandler); } } } /** * @private */ protected function refreshDrawerStates():void { if(this.isTopDrawerDocked && this._isTopDrawerOpen) { this._isTopDrawerOpen = false; } if(this.isRightDrawerDocked && this._isRightDrawerOpen) { this._isRightDrawerOpen = false; } if(this.isBottomDrawerDocked && this._isBottomDrawerOpen) { this._isBottomDrawerOpen = false; } if(this.isLeftDrawerDocked && this._isLeftDrawerOpen) { this._isLeftDrawerOpen = false; } } /** * @private */ protected function refreshOverlayState():void { if(!this._overlaySkin || this._isDragging) { return; } var showOverlay:Boolean = this._isTopDrawerOpen || this._isRightDrawerOpen || this._isBottomDrawerOpen || this._isLeftDrawerOpen; if(showOverlay !== this._overlaySkin.visible) { this._overlaySkin.visible = showOverlay; this._overlaySkin.alpha = showOverlay ? this._overlaySkinOriginalAlpha : 0; } } /** * @private */ protected function handleTapToClose(touch:Touch):void { touch.getLocation(this.stage, HELPER_POINT); if(this !== this.stage.hitTest(HELPER_POINT)) { return; } if(this.isTopDrawerOpen) { this._isTopDrawerOpen = false; this.openOrCloseTopDrawer(); } else if(this.isRightDrawerOpen) { this._isRightDrawerOpen = false; this.openOrCloseRightDrawer(); } else if(this.isBottomDrawerOpen) { this._isBottomDrawerOpen = false; this.openOrCloseBottomDrawer(); } else if(this.isLeftDrawerOpen) { this._isLeftDrawerOpen = false; this.openOrCloseLeftDrawer(); } } /** * @private */ protected function handleTouchBegan(touch:Touch):void { var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); if(exclusiveTouch.getClaim(touch.id)) { //already claimed return; } touch.getLocation(this, HELPER_POINT); var localX:Number = HELPER_POINT.x; var localY:Number = HELPER_POINT.y; if(!this.isTopDrawerOpen && !this.isRightDrawerOpen && !this.isBottomDrawerOpen && !this.isLeftDrawerOpen) { if(this._openGesture == OPEN_GESTURE_NONE) { return; } if(this._openGesture == OPEN_GESTURE_DRAG_CONTENT_EDGE) { var isNearAnyEdge:Boolean = false; if(this._topDrawer && !this.isTopDrawerDocked) { var topInches:Number = localY / (DeviceCapabilities.dpi / Starling.contentScaleFactor); if(topInches >= 0 && topInches <= this._openGestureEdgeSize) { isNearAnyEdge = true; } } if(!isNearAnyEdge) { if(this._rightDrawer && !this.isRightDrawerDocked) { var rightInches:Number = (this.actualWidth - localX) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); if(rightInches >= 0 && rightInches <= this._openGestureEdgeSize) { isNearAnyEdge = true; } } if(!isNearAnyEdge) { if(this._bottomDrawer && !this.isBottomDrawerDocked) { var bottomInches:Number = (this.actualHeight - localY) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); if(bottomInches >= 0 && bottomInches <= this._openGestureEdgeSize) { isNearAnyEdge = true; } } if(!isNearAnyEdge) { if(this._leftDrawer && !this.isLeftDrawerDocked) { var leftInches:Number = localX / (DeviceCapabilities.dpi / Starling.contentScaleFactor); if(leftInches >= 0 && leftInches <= this._openGestureEdgeSize) { isNearAnyEdge = true; } } } } } if(!isNearAnyEdge) { return; } } } else if(this._openMode === OPEN_MODE_BELOW && touch.target !== this) { //when the drawer is opened below, it will only close when //something outside of the drawer is touched return; } //when the drawer is opened above, anything may be touched this.touchPointID = touch.id; this._velocityX = 0; this._velocityY = 0; this._previousVelocityX.length = 0; this._previousVelocityY.length = 0; this._previousTouchTime = getTimer(); this._previousTouchX = this._startTouchX = this._currentTouchX = localX; this._previousTouchY = this._startTouchY = this._currentTouchY = localY; this._isDragging = false; this._isDraggingTopDrawer = false; this._isDraggingRightDrawer = false; this._isDraggingBottomDrawer = false; this._isDraggingLeftDrawer = false; exclusiveTouch.addEventListener(Event.CHANGE, exclusiveTouch_changeHandler); } /** * @private */ protected function handleTouchMoved(touch:Touch):void { touch.getLocation(this, HELPER_POINT); this._currentTouchX = HELPER_POINT.x; this._currentTouchY = HELPER_POINT.y; var now:int = getTimer(); var timeOffset:int = now - this._previousTouchTime; if(timeOffset > 0) { //we're keeping previous velocity updates to improve accuracy this._previousVelocityX[this._previousVelocityX.length] = this._velocityX; if(this._previousVelocityX.length > MAXIMUM_SAVED_VELOCITY_COUNT) { this._previousVelocityX.shift(); } this._previousVelocityY[this._previousVelocityY.length] = this._velocityY; if(this._previousVelocityY.length > MAXIMUM_SAVED_VELOCITY_COUNT) { this._previousVelocityY.shift(); } this._velocityX = (this._currentTouchX - this._previousTouchX) / timeOffset; this._velocityY = (this._currentTouchY - this._previousTouchY) / timeOffset; this._previousTouchTime = now; this._previousTouchX = this._currentTouchX; this._previousTouchY = this._currentTouchY; } } /** * @private */ protected function handleDragEnd():void { //take the average for more accuracy var sum:Number = this._velocityX * CURRENT_VELOCITY_WEIGHT; var velocityCount:int = this._previousVelocityX.length; var totalWeight:Number = CURRENT_VELOCITY_WEIGHT; for(var i:int = 0; i < velocityCount; i++) { var weight:Number = VELOCITY_WEIGHTS[i]; sum += this._previousVelocityX.shift() * weight; totalWeight += weight; } var inchesPerSecondX:Number = 1000 * (sum / totalWeight) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); sum = this._velocityY * CURRENT_VELOCITY_WEIGHT; velocityCount = this._previousVelocityY.length; totalWeight = CURRENT_VELOCITY_WEIGHT; for(i = 0; i < velocityCount; i++) { weight = VELOCITY_WEIGHTS[i]; sum += this._previousVelocityY.shift() * weight; totalWeight += weight; } var inchesPerSecondY:Number = 1000 * (sum / totalWeight) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); this._isDragging = false; if(this._isDraggingTopDrawer) { this._isDraggingTopDrawer = false; if(!this._isTopDrawerOpen && inchesPerSecondY > this._minimumDrawerThrowVelocity) { this._isTopDrawerOpen = true; } else if(this._isTopDrawerOpen && inchesPerSecondY < -this._minimumDrawerThrowVelocity) { this._isTopDrawerOpen = false; } else if(this._openMode === OPEN_MODE_ABOVE) { this._isTopDrawerOpen = roundToNearest(this._topDrawer.y, this._topDrawer.height) == 0; } else //below { this._isTopDrawerOpen = roundToNearest(this._content.y, this._topDrawer.height) != 0; } this.openOrCloseTopDrawer(); } else if(this._isDraggingRightDrawer) { this._isDraggingRightDrawer = false; if(!this._isRightDrawerOpen && inchesPerSecondX < -this._minimumDrawerThrowVelocity) { this._isRightDrawerOpen = true; } else if(this._isRightDrawerOpen && inchesPerSecondX > this._minimumDrawerThrowVelocity) { this._isRightDrawerOpen = false; } else if(this._openMode === OPEN_MODE_ABOVE) { this._isRightDrawerOpen = roundToNearest(this.actualWidth - this._rightDrawer.x, this._rightDrawer.width) != 0; } else //bottom { var positionToCheck:Number = this._content.x; if(this.isLeftDrawerDocked) { positionToCheck -= this._leftDrawer.width; } this._isRightDrawerOpen = roundToNearest(positionToCheck, this._rightDrawer.width) != 0; } this.openOrCloseRightDrawer(); } else if(this._isDraggingBottomDrawer) { this._isDraggingBottomDrawer = false; if(!this._isBottomDrawerOpen && inchesPerSecondY < -this._minimumDrawerThrowVelocity) { this._isBottomDrawerOpen = true; } else if(this._isBottomDrawerOpen && inchesPerSecondY > this._minimumDrawerThrowVelocity) { this._isBottomDrawerOpen = false; } else if(this._openMode === OPEN_MODE_ABOVE) { this._isBottomDrawerOpen = roundToNearest(this.actualHeight - this._bottomDrawer.y, this._bottomDrawer.height) != 0; } else //below { positionToCheck = this._content.y; if(this.isTopDrawerDocked) { positionToCheck -= this._topDrawer.height; } this._isBottomDrawerOpen = roundToNearest(positionToCheck, this._bottomDrawer.height) != 0; } this.openOrCloseBottomDrawer(); } else if(this._isDraggingLeftDrawer) { this._isDraggingLeftDrawer = false; if(!this._isLeftDrawerOpen && inchesPerSecondX > this._minimumDrawerThrowVelocity) { this._isLeftDrawerOpen = true; } else if(this._isLeftDrawerOpen && inchesPerSecondX < -this._minimumDrawerThrowVelocity) { this._isLeftDrawerOpen = false; } else if(this._openMode === OPEN_MODE_ABOVE) { this._isLeftDrawerOpen = roundToNearest(this._leftDrawer.x, this._leftDrawer.width) == 0; } else //below { this._isLeftDrawerOpen = roundToNearest(this._content.x, this._leftDrawer.width) != 0; } this.openOrCloseLeftDrawer(); } } /** * @private */ protected function handleDragMove():void { var contentX:Number = 0; var contentY:Number = 0; if(this.isLeftDrawerDocked) { contentX = this._leftDrawer.width; } if(this.isTopDrawerDocked) { contentY = this._topDrawer.height; } if(this._isDraggingLeftDrawer) { var leftDrawerWidth:Number = this._leftDrawer.width; if(this.isLeftDrawerOpen) { contentX = leftDrawerWidth + this._currentTouchX - this._startTouchX; } else { contentX = this._currentTouchX - this._startTouchX; } if(contentX < 0) { contentX = 0; } if(contentX > leftDrawerWidth) { contentX = leftDrawerWidth; } } else if(this._isDraggingRightDrawer) { var rightDrawerWidth:Number = this._rightDrawer.width; if(this.isRightDrawerOpen) { contentX = -rightDrawerWidth + this._currentTouchX - this._startTouchX; } else { contentX = this._currentTouchX - this._startTouchX; } if(contentX < -rightDrawerWidth) { contentX = -rightDrawerWidth; } if(contentX > 0) { contentX = 0; } if(this.isLeftDrawerDocked && this._openMode === OPEN_MODE_BELOW) { contentX += this._leftDrawer.width; } } else if(this._isDraggingTopDrawer) { var topDrawerHeight:Number = this._topDrawer.height; if(this.isTopDrawerOpen) { contentY = topDrawerHeight + this._currentTouchY - this._startTouchY; } else { contentY = this._currentTouchY - this._startTouchY; } if(contentY < 0) { contentY = 0; } if(contentY > topDrawerHeight) { contentY = topDrawerHeight; } } else if(this._isDraggingBottomDrawer) { var bottomDrawerHeight:Number = this._bottomDrawer.height; if(this.isBottomDrawerOpen) { contentY = -bottomDrawerHeight + this._currentTouchY - this._startTouchY; } else { contentY = this._currentTouchY - this._startTouchY; } if(contentY < -bottomDrawerHeight) { contentY = -bottomDrawerHeight; } if(contentY > 0) { contentY = 0; } if(this.isTopDrawerDocked && this._openMode === OPEN_MODE_BELOW) { contentY += this._topDrawer.height; } } if(this._openMode === OPEN_MODE_ABOVE) { if(this._isDraggingTopDrawer) { this._topDrawer.y = contentY - this._topDrawer.height; } else if(this._isDraggingRightDrawer) { this._rightDrawer.x = this.actualWidth + contentX; } else if(this._isDraggingBottomDrawer) { this._bottomDrawer.y = this.actualHeight + contentY; } else if(this._isDraggingLeftDrawer) { this._leftDrawer.x = contentX - this._leftDrawer.width; } } else //below { this._content.x = contentX; this._content.y = contentY; } if(this._isDraggingTopDrawer) { this.topDrawerOpenOrCloseTween_onUpdate(); } else if(this._isDraggingRightDrawer) { this.rightDrawerOpenOrCloseTween_onUpdate(); } else if(this._isDraggingBottomDrawer) { this.bottomDrawerOpenOrCloseTween_onUpdate(); } else if(this._isDraggingLeftDrawer) { this.leftDrawerOpenOrCloseTween_onUpdate(); } } /** * @private */ protected function checkForDragToClose():void { var horizontalInchesMoved:Number = (this._currentTouchX - this._startTouchX) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); var verticalInchesMoved:Number = (this._currentTouchY - this._startTouchY) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); if(this.isLeftDrawerOpen && horizontalInchesMoved <= -this._minimumDragDistance) { this._isDragging = true; this._isDraggingLeftDrawer = true; this.prepareLeftDrawer(); } else if(this.isRightDrawerOpen && horizontalInchesMoved >= this._minimumDragDistance) { this._isDragging = true; this._isDraggingRightDrawer = true; this.prepareRightDrawer(); } else if(this.isTopDrawerOpen && verticalInchesMoved <= -this._minimumDragDistance) { this._isDragging = true; this._isDraggingTopDrawer = true; this.prepareTopDrawer(); } else if(this.isBottomDrawerOpen && verticalInchesMoved >= this._minimumDragDistance) { this._isDragging = true; this._isDraggingBottomDrawer = true; this.prepareBottomDrawer(); } if(this._isDragging) { if(this._overlaySkin) { this._overlaySkin.visible = true; this._overlaySkin.alpha = this._overlaySkinOriginalAlpha; } this._startTouchY = this._currentTouchY; var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); exclusiveTouch.removeEventListener(Event.CHANGE, exclusiveTouch_changeHandler); exclusiveTouch.claimTouch(this.touchPointID, this); this.dispatchEventWith(FeathersEventType.BEGIN_INTERACTION); } } /** * @private */ protected function checkForDragToOpen():void { var horizontalInchesMoved:Number = (this._currentTouchX - this._startTouchX) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); var verticalInchesMoved:Number = (this._currentTouchY - this._startTouchY) / (DeviceCapabilities.dpi / Starling.contentScaleFactor); if(this._leftDrawer && !this.isLeftDrawerDocked && horizontalInchesMoved >= this._minimumDragDistance) { this._isDragging = true; this._isDraggingLeftDrawer = true; this.prepareLeftDrawer(); } else if(this._rightDrawer && !this.isRightDrawerDocked && horizontalInchesMoved <= -this._minimumDragDistance) { this._isDragging = true; this._isDraggingRightDrawer = true; this.prepareRightDrawer(); } else if(this._topDrawer && !this.isTopDrawerDocked && verticalInchesMoved >= this._minimumDragDistance) { this._isDragging = true; this._isDraggingTopDrawer = true; this.prepareTopDrawer(); } else if(this._bottomDrawer && !this.isBottomDrawerDocked && verticalInchesMoved <= -this._minimumDragDistance) { this._isDragging = true; this._isDraggingBottomDrawer = true; this.prepareBottomDrawer(); } if(this._isDragging) { if(this._overlaySkin) { this._overlaySkin.visible = true; this._overlaySkin.alpha = 0; } this._startTouchY = this._currentTouchY; var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); exclusiveTouch.claimTouch(this.touchPointID, this); exclusiveTouch.removeEventListener(Event.CHANGE, exclusiveTouch_changeHandler); this.dispatchEventWith(FeathersEventType.BEGIN_INTERACTION); } } /** * @private */ protected function positionOverlaySkin():void { if(!this._overlaySkin) { return; } if(this.isLeftDrawerDocked) { this._overlaySkin.x = this._leftDrawer.x; } else if(this._openMode === OPEN_MODE_ABOVE && this._leftDrawer) { this._overlaySkin.x = this._leftDrawer.x + this._leftDrawer.width; } else //below or no left drawer { this._overlaySkin.x = this._content.x; } if(this.isTopDrawerDocked) { this._overlaySkin.y = this._topDrawer.y; } else if(this._openMode === OPEN_MODE_ABOVE && this._topDrawer) { this._overlaySkin.y = this._topDrawer.y + this._topDrawer.height; } else //below or now top drawer { this._overlaySkin.y = this._content.y; } } /** * @private */ protected function topDrawerOpenOrCloseTween_onUpdate():void { if(this._overlaySkin) { if(this._openMode === OPEN_MODE_ABOVE) { var ratio:Number = 1 + this._topDrawer.y / this._topDrawer.height; } else //below { ratio = this._content.y / this._topDrawer.height; } this._overlaySkin.alpha = this._overlaySkinOriginalAlpha * ratio; } this.openOrCloseTween_onUpdate(); } /** * @private */ protected function rightDrawerOpenOrCloseTween_onUpdate():void { if(this._overlaySkin) { if(this._openMode === OPEN_MODE_ABOVE) { var ratio:Number = -(this._rightDrawer.x - this.actualWidth) / this._rightDrawer.width; } else //below { ratio = (this.actualWidth - this._content.x - this._content.width) / this._rightDrawer.width; } this._overlaySkin.alpha = this._overlaySkinOriginalAlpha * ratio; } this.openOrCloseTween_onUpdate(); } /** * @private */ protected function bottomDrawerOpenOrCloseTween_onUpdate():void { if(this._overlaySkin) { if(this._openMode === OPEN_MODE_ABOVE) { var ratio:Number = -(this._bottomDrawer.y - this.actualHeight) / this._bottomDrawer.height; } else //below { ratio = (this.actualHeight - this._content.y - this._content.height) / this._bottomDrawer.height; } this._overlaySkin.alpha = this._overlaySkinOriginalAlpha * ratio; } this.openOrCloseTween_onUpdate(); } /** * @private */ protected function leftDrawerOpenOrCloseTween_onUpdate():void { if(this._overlaySkin) { if(this._openMode === OPEN_MODE_ABOVE) { var ratio:Number = 1 + this._leftDrawer.x / this._leftDrawer.width; } else //below { ratio = this._content.x / this._leftDrawer.width; } this._overlaySkin.alpha = this._overlaySkinOriginalAlpha * ratio; } this.openOrCloseTween_onUpdate(); } /** * @private */ protected function openOrCloseTween_onUpdate():void { if(this._clipDrawers && this._openMode === OPEN_MODE_BELOW) { var isTopDrawerDocked:Boolean = this.isTopDrawerDocked; var isRightDrawerDocked:Boolean = this.isRightDrawerDocked; var isBottomDrawerDocked:Boolean = this.isBottomDrawerDocked; var isLeftDrawerDocked:Boolean = this.isLeftDrawerDocked; var mask:Quad = this._topDrawer.mask as Quad; if(mask) { mask.height = this._content.y; } mask = this._rightDrawer.mask as Quad; if(mask) { var rightClipWidth:Number = -this._content.x; if(isLeftDrawerDocked) { rightClipWidth += this.leftDrawer.width; if(this._leftDrawerDivider) { rightClipWidth += this._leftDrawerDivider.width; } } mask.x = this._rightDrawer.width - rightClipWidth; mask.width = rightClipWidth; } mask = this._bottomDrawer.mask as Quad; if(mask) { var bottomClipHeight:Number = -this._content.y; if(isTopDrawerDocked) { bottomClipHeight += this.topDrawer.height; if(this._topDrawerDivider) { bottomClipHeight += this._topDrawerDivider.height; } } mask.y = this._bottomDrawer.height - bottomClipHeight; mask.height = bottomClipHeight; } mask = this._leftDrawer.mask as Quad; if(mask) { mask.width = this._content.x; } var contentX:Number = this._content.x; var contentY:Number = this._content.y; if(isTopDrawerDocked) { if(isLeftDrawerDocked) { this._topDrawer.x = contentX - this._leftDrawer.width; } else { this._topDrawer.x = contentX; } if(this._topDrawerDivider) { this._topDrawerDivider.x = this._topDrawer.x; this._topDrawerDivider.y = contentY - this._topDrawerDivider.height; this._topDrawer.y = this._topDrawerDivider.y - this._topDrawer.height; } else { this._topDrawer.y = contentY - this._topDrawer.height; } } if(isRightDrawerDocked) { if(this._leftDrawerDivider) { this._rightDrawerDivider.x = contentX + this._content.width; this._rightDrawer.x = this._rightDrawerDivider.x + this._rightDrawerDivider.width; this._rightDrawerDivider.y = contentY; } else { this._rightDrawer.x = contentX + this._content.width; } this._rightDrawer.y = contentY; } if(isBottomDrawerDocked) { if(isLeftDrawerDocked) { this._bottomDrawer.x = contentX - this._leftDrawer.width; } else { this._bottomDrawer.x = contentX; } if(this._bottomDrawerDivider) { this._bottomDrawerDivider.x = this._bottomDrawer.x; this._bottomDrawerDivider.y = contentY + this._content.height; this._bottomDrawer.y = this._bottomDrawerDivider.y + this._bottomDrawerDivider.height; } else { this._bottomDrawer.y = contentY + this._content.height; } } if(isLeftDrawerDocked) { if(this._leftDrawerDivider) { this._leftDrawerDivider.x = contentX - this._leftDrawerDivider.width; this._leftDrawer.x = this._leftDrawerDivider.x - this._leftDrawer.width; this._leftDrawerDivider.y = contentY; } else { this._leftDrawer.x = contentX - this._leftDrawer.width; } this._leftDrawer.y = contentY; } } if(this._overlaySkin) { this.positionOverlaySkin(); } } /** * @private */ protected function topDrawerOpenOrCloseTween_onComplete():void { if(this._overlaySkin) { this._overlaySkin.alpha = this._overlaySkinOriginalAlpha; } this._openOrCloseTween = null; this._topDrawer.mask = null; var isTopDrawerOpen:Boolean = this.isTopDrawerOpen; var isTopDrawerDocked:Boolean = this.isTopDrawerDocked; this._topDrawer.visible = isTopDrawerOpen || isTopDrawerDocked; if(this._overlaySkin) { this._overlaySkin.visible = isTopDrawerOpen; } if(isTopDrawerOpen) { this.dispatchEventWith(Event.OPEN, false, this._topDrawer); } else { this.dispatchEventWith(Event.CLOSE, false, this._topDrawer); } } /** * @private */ protected function rightDrawerOpenOrCloseTween_onComplete():void { this._openOrCloseTween = null; this._rightDrawer.mask = null; var isRightDrawerOpen:Boolean = this.isRightDrawerOpen; var isRightDrawerDocked:Boolean = this.isRightDrawerDocked; this._rightDrawer.visible = isRightDrawerOpen || isRightDrawerDocked; if(this._overlaySkin) { this._overlaySkin.visible = isRightDrawerOpen; } if(isRightDrawerOpen) { this.dispatchEventWith(Event.OPEN, false, this._rightDrawer); } else { this.dispatchEventWith(Event.CLOSE, false, this._rightDrawer); } } /** * @private */ protected function bottomDrawerOpenOrCloseTween_onComplete():void { this._openOrCloseTween = null; this._bottomDrawer.mask = null; var isBottomDrawerOpen:Boolean = this.isBottomDrawerOpen; var isBottomDrawerDocked:Boolean = this.isBottomDrawerDocked; this._bottomDrawer.visible = isBottomDrawerOpen || isBottomDrawerDocked; if(this._overlaySkin) { this._overlaySkin.visible = isBottomDrawerOpen; } if(isBottomDrawerOpen) { this.dispatchEventWith(Event.OPEN, false, this._bottomDrawer); } else { this.dispatchEventWith(Event.CLOSE, false, this._bottomDrawer); } } /** * @private */ protected function leftDrawerOpenOrCloseTween_onComplete():void { this._openOrCloseTween = null; this._leftDrawer.mask = null; var isLeftDrawerOpen:Boolean = this.isLeftDrawerOpen; var isLeftDrawerDocked:Boolean = this.isLeftDrawerDocked; this._leftDrawer.visible = isLeftDrawerOpen || isLeftDrawerDocked; if(this._overlaySkin) { this._overlaySkin.visible = isLeftDrawerOpen; } if(isLeftDrawerOpen) { this.dispatchEventWith(Event.OPEN, false, this._leftDrawer); } else { this.dispatchEventWith(Event.CLOSE, false, this._leftDrawer); } } /** * @private */ protected function content_eventDispatcherChangeHandler(event:Event):void { this.refreshCurrentEventTarget(); } /** * @private */ protected function drawers_addedToStageHandler(event:Event):void { this.stage.addEventListener(ResizeEvent.RESIZE, stage_resizeHandler); //using priority here is a hack so that objects higher up in the //display list have a chance to cancel the event first. var priority:int = -getDisplayObjectDepthFromStage(this); Starling.current.nativeStage.addEventListener(KeyboardEvent.KEY_DOWN, drawers_nativeStage_keyDownHandler, false, priority, true); } /** * @private */ protected function drawers_removedFromStageHandler(event:Event):void { if(this.touchPointID >= 0) { var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); exclusiveTouch.removeEventListener(Event.CHANGE, exclusiveTouch_changeHandler); } this.touchPointID = -1; this._isDragging = false; this._isDraggingTopDrawer = false; this._isDraggingRightDrawer = false; this._isDraggingBottomDrawer = false; this._isDraggingLeftDrawer = false; this.stage.removeEventListener(ResizeEvent.RESIZE, stage_resizeHandler); Starling.current.nativeStage.removeEventListener(KeyboardEvent.KEY_DOWN, drawers_nativeStage_keyDownHandler); } /** * @private */ protected function drawers_touchHandler(event:TouchEvent):void { if(!this._isEnabled || this._openOrCloseTween) { this.touchPointID = -1; return; } if(this.touchPointID >= 0) { var touch:Touch = event.getTouch(this, null, this.touchPointID); if(!touch) { return; } if(touch.phase == TouchPhase.MOVED) { this.handleTouchMoved(touch); if(!this._isDragging) { if(this.isTopDrawerOpen || this.isRightDrawerOpen || this.isBottomDrawerOpen || this.isLeftDrawerOpen) { this.checkForDragToClose(); } else { this.checkForDragToOpen(); } } if(this._isDragging) { this.handleDragMove(); } } else if(touch.phase == TouchPhase.ENDED) { this.touchPointID = -1; if(this._isDragging) { this.handleDragEnd(); this.dispatchEventWith(FeathersEventType.END_INTERACTION); } else { ExclusiveTouch.forStage(this.stage).removeEventListener(Event.CHANGE, exclusiveTouch_changeHandler); if(this.isTopDrawerOpen || this.isRightDrawerOpen || this.isBottomDrawerOpen || this.isLeftDrawerOpen) { //there is no drag, so we may have a tap this.handleTapToClose(touch); } } } } else { touch = event.getTouch(this, TouchPhase.BEGAN); if(!touch) { return; } this.handleTouchBegan(touch); } } /** * @private */ protected function exclusiveTouch_changeHandler(event:Event, touchID:int):void { if(this.touchPointID < 0 || this.touchPointID != touchID || this._isDragging) { return; } var exclusiveTouch:ExclusiveTouch = ExclusiveTouch.forStage(this.stage); if(exclusiveTouch.getClaim(touchID) == this) { return; } this.touchPointID = -1; } /** * @private */ protected function stage_resizeHandler(event:ResizeEvent):void { this.invalidate(INVALIDATION_FLAG_SIZE); } /** * @private */ protected function drawers_nativeStage_keyDownHandler(event:KeyboardEvent):void { if(event.isDefaultPrevented()) { //someone else already handled this one return; } if(event.keyCode == Keyboard.BACK) { var isAnyDrawerOpen:Boolean = false; if(this.isTopDrawerOpen) { this.toggleTopDrawer(); isAnyDrawerOpen = true; } else if(this.isRightDrawerOpen) { this.toggleRightDrawer(); isAnyDrawerOpen = true; } else if(this.isBottomDrawerOpen) { this.toggleBottomDrawer(); isAnyDrawerOpen = true; } else if(this.isLeftDrawerOpen) { this.toggleLeftDrawer(); isAnyDrawerOpen = true; } if(isAnyDrawerOpen) { event.preventDefault(); } } } /** * @private */ protected function content_topDrawerToggleEventTypeHandler(event:Event):void { if(!this._topDrawer || this.isTopDrawerDocked) { return; } this._isTopDrawerOpen = !this._isTopDrawerOpen; this.openOrCloseTopDrawer(); } /** * @private */ protected function content_rightDrawerToggleEventTypeHandler(event:Event):void { if(!this._rightDrawer || this.isRightDrawerDocked) { return; } this._isRightDrawerOpen = !this._isRightDrawerOpen; this.openOrCloseRightDrawer(); } /** * @private */ protected function content_bottomDrawerToggleEventTypeHandler(event:Event):void { if(!this._bottomDrawer || this.isBottomDrawerDocked) { return; } this._isBottomDrawerOpen = !this._isBottomDrawerOpen; this.openOrCloseBottomDrawer(); } /** * @private */ protected function content_leftDrawerToggleEventTypeHandler(event:Event):void { if(!this._leftDrawer || this.isLeftDrawerDocked) { return; } this._isLeftDrawerOpen = !this._isLeftDrawerOpen; this.openOrCloseLeftDrawer(); } /** * @private */ protected function content_resizeHandler(event:Event):void { if(this._isValidating || this._autoSizeMode != AUTO_SIZE_MODE_CONTENT) { return; } this.invalidate(INVALIDATION_FLAG_SIZE); } /** * @private */ protected function drawer_resizeHandler(event:Event):void { if(this._isValidating) { return; } this.invalidate(INVALIDATION_FLAG_SIZE); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy