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

scaffold.libs_as.feathers.motion.transitions.TabBarSlideTransitionManager.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.motion.transitions
{
	import feathers.controls.ScreenNavigator;
	import feathers.controls.TabBar;

	import starling.animation.Transitions;
	import starling.animation.Tween;
	import starling.core.Starling;
	import starling.display.DisplayObject;
	import starling.events.Event;

	/**
	 * Slides new screens from the left or right depending on the old and new
	 * selected index values of a TabBar control.
	 *
	 * @see feathers.controls.ScreenNavigator
	 * @see feathers.controls.TabBar
	 */
	public class TabBarSlideTransitionManager
	{
		/**
		 * Constructor.
		 */
		public function TabBarSlideTransitionManager(navigator:ScreenNavigator, tabBar:TabBar)
		{
			if(!navigator)
			{
				throw new ArgumentError("ScreenNavigator cannot be null.");
			}
			this.navigator = navigator;
			this.tabBar = tabBar;
			this._activeIndex = this._pendingIndex = tabBar.selectedIndex;
			this.tabBar.addEventListener(Event.CHANGE, tabBar_changeHandler);
			this.navigator.transition = this.onTransition;
		}

		/**
		 * The ScreenNavigator being managed.
		 */
		protected var navigator:ScreenNavigator;

		/**
		 * The TabBar that controls the navigation.
		 */
		protected var tabBar:TabBar;

		/**
		 * @private
		 */
		protected var _activeTransition:Tween;

		/**
		 * @private
		 */
		protected var _savedOtherTarget:DisplayObject;

		/**
		 * @private
		 */
		protected var _savedCompleteHandler:Function;

		/**
		 * @private
		 */
		protected var _oldScreen:DisplayObject;

		/**
		 * @private
		 */
		protected var _newScreen:DisplayObject;

		/**
		 * @private
		 */
		protected var _pendingIndex:int;

		/**
		 * @private
		 */
		protected var _activeIndex:int;

		/**
		 * @private
		 */
		protected var _isFromRight:Boolean = true;

		/**
		 * @private
		 */
		protected var _isWaitingOnTabBarChange:Boolean = true;

		/**
		 * @private
		 */
		protected var _isWaitingOnTransitionChange:Boolean = true;

		/**
		 * The duration of the transition, measured in seconds.
		 *
		 * @default 0.25
		 */
		public var duration:Number = 0.25;

		/**
		 * A delay before the transition starts, measured in seconds. This may
		 * be required on low-end systems that will slow down for a short time
		 * after heavy texture uploads.
		 *
		 * @default 0.1
		 */
		public var delay:Number = 0.1;

		/**
		 * The easing function to use.
		 *
		 * @default starling.animation.Transitions.EASE_OUT
		 */
		public var ease:Object = Transitions.EASE_OUT;

		/**
		 * Determines if the next transition should be skipped. After the
		 * transition, this value returns to false.
		 *
		 * @default false
		 */
		public var skipNextTransition:Boolean = false;

		/**
		 * The function passed to the transition property of the
		 * ScreenNavigator.
		 */
		protected function onTransition(oldScreen:DisplayObject, newScreen:DisplayObject, onComplete:Function):void
		{
			this._oldScreen = oldScreen;
			this._newScreen = newScreen;
			this._savedCompleteHandler = onComplete;

			if(!this._isWaitingOnTabBarChange)
			{
				this.transitionNow();
			}
			else
			{
				this._isWaitingOnTransitionChange = false;
			}
		}

		/**
		 * @private
		 */
		protected function transitionNow():void
		{
			this._activeIndex = this._pendingIndex;
			if(this._activeTransition)
			{
				this._savedOtherTarget  = null;
				Starling.juggler.remove(this._activeTransition);
				this._activeTransition = null;
			}

			if(!this._oldScreen || !this._newScreen || this.skipNextTransition)
			{
				this.skipNextTransition = false;
				var savedCompleteHandler:Function = this._savedCompleteHandler;
				this._savedCompleteHandler = null;
				if(this._oldScreen)
				{
					this._oldScreen.x = 0;
				}
				if(this._newScreen)
				{
					this._newScreen.x = 0;
				}
				if(savedCompleteHandler != null)
				{
					savedCompleteHandler();
				}
			}
			else
			{
				this._oldScreen.x = 0;
				var activeTransition_onUpdate:Function;
				if(this._isFromRight)
				{
					this._newScreen.x = this.navigator.width;
					activeTransition_onUpdate = this.activeTransitionFromRight_onUpdate;
				}
				else
				{
					this._newScreen.x = -this.navigator.width;
					activeTransition_onUpdate = this.activeTransitionFromLeft_onUpdate;
				}
				this._savedOtherTarget = this._oldScreen;
				this._activeTransition = new Tween(this._newScreen, this.duration, this.ease);
				this._activeTransition.animate("x", 0);
				this._activeTransition.delay = this.delay;
				this._activeTransition.onUpdate = activeTransition_onUpdate;
				this._activeTransition.onComplete = activeTransition_onComplete;
				Starling.juggler.add(this._activeTransition);
			}

			this._oldScreen = null;
			this._newScreen = null;
			this._isWaitingOnTabBarChange = true;
			this._isWaitingOnTransitionChange = true;
		}

		/**
		 * @private
		 */
		protected function activeTransitionFromRight_onUpdate():void
		{
			if(this._savedOtherTarget)
			{
				var newScreen:DisplayObject = DisplayObject(this._activeTransition.target);
				this._savedOtherTarget.x = newScreen.x - this.navigator.width;
			}
		}

		/**
		 * @private
		 */
		protected function activeTransitionFromLeft_onUpdate():void
		{
			if(this._savedOtherTarget)
			{
				var newScreen:DisplayObject = DisplayObject(this._activeTransition.target);
				this._savedOtherTarget.x = newScreen.x + this.navigator.width;
			}
		}

		/**
		 * @private
		 */
		protected function activeTransition_onComplete():void
		{
			this._savedOtherTarget = null;
			this._activeTransition = null;
			if(this._savedCompleteHandler != null)
			{
				this._savedCompleteHandler();
			}
		}

		/**
		 * @private
		 */
		protected function tabBar_changeHandler(event:Event):void
		{
			this._pendingIndex = this.tabBar.selectedIndex;
			if(this._pendingIndex == this._activeIndex)
			{
				//someone is changing tabs very quickly, and they just went back
				//to the tab we're currently transitioning to. cancel the next
				//transition.
				this._isWaitingOnTabBarChange = true;
				return;
			}
			this._isFromRight = this._pendingIndex > this._activeIndex;

			if(!this._isWaitingOnTransitionChange)
			{
				this.transitionNow();
			}
			else
			{
				this._isWaitingOnTabBarChange = false;
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy