| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package spark.transitions |
| { |
| |
| import flash.display.DisplayObject; |
| import flash.display.DisplayObjectContainer; |
| import flash.display.Stage; |
| import flash.events.Event; |
| import flash.events.EventDispatcher; |
| import flash.geom.Matrix; |
| import flash.geom.Point; |
| import flash.geom.Rectangle; |
| |
| import mx.core.FlexGlobals; |
| import mx.core.IVisualElementContainer; |
| import mx.core.UIComponent; |
| import mx.core.mx_internal; |
| import mx.effects.IEffect; |
| import mx.effects.Parallel; |
| import mx.events.EffectEvent; |
| import mx.events.FlexEvent; |
| import mx.geom.TransformOffsets; |
| import mx.managers.SystemManager; |
| |
| import spark.components.ActionBar; |
| import spark.components.Group; |
| import spark.components.TabbedViewNavigator; |
| import spark.components.View; |
| import spark.components.ViewNavigator; |
| import spark.components.supportClasses.ButtonBarBase; |
| import spark.components.supportClasses.ViewNavigatorBase; |
| import spark.effects.Animate; |
| import spark.effects.Fade; |
| import spark.effects.animation.MotionPath; |
| import spark.effects.animation.SimpleMotionPath; |
| import spark.effects.easing.IEaser; |
| import spark.effects.easing.Sine; |
| import spark.primitives.BitmapImage; |
| import spark.utils.BitmapUtil; |
| |
| use namespace mx_internal; |
| |
| /** |
| * Dispatched when the transition starts. |
| * |
| * @eventType mx.events.FlexEvent.TRANSITION_START |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| [Event(name="transitionStart", type="mx.events.FlexEvent")] |
| |
| /** |
| * Dispatched when the transition completes. |
| * |
| * @eventType mx.events.FlexEvent.TRANSITION_START |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| [Event(name="transitionEnd", type="mx.events.FlexEvent")] |
| |
| |
| /** |
| * The ViewTransitionBase class is the base class for all view transitions. |
| * It is not intended to be used as a transition on its own. |
| * In addition to providing common convenience and helper methods used by |
| * view transitions, this class provides a default action bar transition |
| * sequence. |
| * |
| * <p>When a view transition is initialized, the owning view navigator |
| * sets the <code>startView</code> and <code>endView</code> properties |
| * to the views the transition animates. |
| * The <code>navigator</code> property is |
| * set to the view navigator.</p> |
| * |
| * <p>The lifecycle of a transition is as follows:</p> |
| * <ul> |
| * <li>The transition starts with |
| * the <code>captureStartValues()</code> method. |
| * When this method is called, the navigator is currently in the |
| * start state. |
| * At this time, the transition should capture any start values |
| * or bitmaps that it requires. </li> |
| * <li>A validation pass is performed on the pending |
| * view, and the <code>captureEndValues()</code> method is called. |
| * At this time, the transition captures any properties or |
| * bitmaps representations from the pending view.</li> |
| * <li>The <code>prepareForPlay()</code> method is then called, |
| * which allows the transition to perform any further preparations, |
| * such as preparing a Spark effects sequence, |
| * or positioning transient elements on the display list.</li> |
| * <li>After a final validation pass, if necessary, |
| * the <code>play()</code> method is called by the navigator |
| * to perform the actual transition.</li> |
| * <li>Prior to any animation starting, the <code>start</code> |
| * event is dispatched.</li> |
| * <li>When a transition completes, it dispatches an |
| * <code>end</code> event.</li> |
| * </ul> |
| * |
| * <p><strong>Note:</strong>Create and configure view transitions in ActionScript; |
| * you cannot create them in MXML.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public class ViewTransitionBase extends EventDispatcher |
| { |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constants |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constant used in tandem with the actionBarTransitionMode property to |
| * hint the default action bar transition behavior. |
| */ |
| mx_internal static const ACTION_BAR_MODE_FADE:String = "fade"; |
| |
| /** |
| * Constant used in tandem with the actionBarTransitionMode property to |
| * hint the default action bar transition behavior. |
| */ |
| mx_internal static const ACTION_BAR_MODE_FADE_AND_SLIDE:String = "fadeAndSlide"; |
| |
| /** |
| * Constant used in tandem with the actionBarTransitionMode property to |
| * hint the default action bar transition behavior. |
| */ |
| mx_internal static const ACTION_BAR_MODE_NONE:String = "none"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function ViewTransitionBase() |
| { |
| super(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Flag set when we've determined that we need to transition the navigator |
| * in its entirety and cannot transition the control bars independently. |
| */ |
| protected var consolidatedTransition:Boolean = false; |
| |
| /** |
| * @private |
| * startView's action bar height. |
| */ |
| private var cachedActionBarHeight:Number; |
| |
| /** |
| * @private |
| * startView's action bar width. |
| */ |
| private var cachedActionBarWidth:Number; |
| |
| /** |
| * @private |
| * Transient display object used to hold temporary bitmap snapshots |
| * during transition. |
| */ |
| private var transitionGroup:Group; |
| |
| /** |
| * @private |
| * Flag to assist with cleanup of any constructs used only for vertical |
| * transitions (e.g. clipping masks). |
| */ |
| private var verticalTransition:Boolean; |
| |
| /** |
| * @private |
| * Flag used to determine whether the transition should wait a frame when |
| * it receives the EFFECT_END event. This is true by default. It is only |
| * set to false when the endTransitions() method is called. |
| */ |
| private static var renderLastFrame:Boolean = true; |
| |
| /** |
| * @private |
| * Private vector that stores all the active transitions. |
| */ |
| private static var activeTransitions:Vector.<ViewTransitionBase> = new Vector.<ViewTransitionBase>(); |
| |
| /** |
| * @private |
| * Ends all currently active view transitions. |
| */ |
| mx_internal static function endTransitions():void |
| { |
| // Prevent the transitions from waiting a frame when they receive the |
| // EFFECT_END event. See effectComplete(). |
| renderLastFrame = false; |
| |
| // End all active transitions. They will be removed from the vector |
| // in transitionComplete(). |
| for (var i:int = 0; i < activeTransitions.length; i++) |
| activeTransitions[i].effect.end(); |
| |
| // Restore render flag |
| renderLastFrame = true; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // duration |
| //---------------------------------- |
| |
| private var _duration:Number = 250; |
| |
| /** |
| * Duration of the transition, in milliseconds. |
| * The default may vary depending on the transition |
| * but is defined in ViewTransitionBase as 250 ms. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get duration():Number |
| { |
| return _duration; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set duration(value:Number):void |
| { |
| _duration = value; |
| } |
| |
| //---------------------------------- |
| // easer |
| //---------------------------------- |
| |
| private var _easer:IEaser = new Sine(.5); |
| |
| /** |
| * The easing behavior for this transition. The IEaser object is |
| * generally propagated to the IEffect instance managing the actual |
| * transition animation. |
| * |
| * @default Sine(.5); |
| * |
| * @see spark.effects.easing |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get easer():IEaser |
| { |
| return _easer; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set easer(value:IEaser):void |
| { |
| _easer = value; |
| } |
| |
| //---------------------------------- |
| // effect |
| //---------------------------------- |
| |
| private var _effect:IEffect; |
| |
| /** |
| * Provides access to the underlying IEffect instance which the |
| * transition is using to perform the transition (if any). This property |
| * is only valid after the FlexEvent.TRANSITION_START event even has been |
| * dispatched. |
| * |
| * If a transition does not make use of IEffect to perform the transition |
| * this can be null. |
| * |
| * @default null |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| mx_internal function get effect():IEffect |
| { |
| return _effect; |
| } |
| |
| mx_internal function set effect(value:IEffect):void |
| { |
| _effect = value; |
| } |
| |
| //---------------------------------- |
| // endView |
| //---------------------------------- |
| |
| private var _endView:View; |
| |
| /** |
| * The view that the navigator is transitioning |
| * to, as set by the owning ViewNavigator object. |
| * This property can be null. |
| * |
| * @default null |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get endView():View |
| { |
| return _endView; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set endView(value:View):void |
| { |
| _endView = value; |
| } |
| |
| //---------------------------------- |
| // navigator |
| //---------------------------------- |
| |
| private var _navigator:ViewNavigator; |
| |
| /** |
| * Reference to the owning ViewNavigator instance set by the owning |
| * ViewNavigator. |
| * |
| * @default null |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get navigator():ViewNavigator |
| { |
| return _navigator; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set navigator(value:ViewNavigator):void |
| { |
| _navigator = value; |
| } |
| |
| //---------------------------------- |
| // startView |
| //---------------------------------- |
| |
| private var _startView:View; |
| |
| /** |
| * The currently active view of the view navigator, |
| * as set by the owning view navigator. |
| * This property can be null. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get startView():View |
| { |
| return _startView; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set startView(value:View):void |
| { |
| _startView = value; |
| } |
| |
| //---------------------------------- |
| // suspendBackgroundProcessing |
| //---------------------------------- |
| |
| private var _suspendBackgroundProcessing:Boolean = true; |
| |
| /** |
| * When set to <code>true</code>, the <code>UIComponent.suspendBackgroundProcessing()</code> |
| * method is invoked prior to the transition playing. |
| * This disables Flex's layout manager and improving performance. |
| * Upon completion of the transition, |
| * the layout manager function is restored by a call to the |
| * <code>UIComponent.resumeBackgroundProcessing()</code> method. |
| * |
| * @default false |
| * |
| * @see mx.core.UIComponent#suspendBackgroundProcessing() |
| * @see mx.core.UIComponent#resumeBackgroundProcessing() |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get suspendBackgroundProcessing():Boolean |
| { |
| return _suspendBackgroundProcessing; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set suspendBackgroundProcessing(value:Boolean):void |
| { |
| _suspendBackgroundProcessing = value; |
| } |
| |
| //---------------------------------- |
| // transitionControlsWithContent |
| //---------------------------------- |
| |
| private var _transitionControlsWithContent:Boolean; |
| |
| /** |
| * When set to <code>true</code>, the primary view transition |
| * is used to transition the view navigator in its entirety, |
| * including the action bar. |
| * Specific transitions for the action bar are not performed. |
| * Because the tab bar is associated with the entire application, |
| * and not a view, view transitions do not affect it. |
| * |
| * <p>Note that even when set to <code>false</code>, there are cases |
| * where its not feasible to transition the action bar. |
| * For example, when the action bar does not exist in one of |
| * the two views, or if the action bar changes size.</p> |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function get transitionControlsWithContent():Boolean |
| { |
| return _transitionControlsWithContent; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set transitionControlsWithContent(value:Boolean):void |
| { |
| _transitionControlsWithContent = value; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Private Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // actionBarTransitionMode |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Convenience property used by ViewTransitionBase overrides to hint the behavior of |
| * the default action bar transition as appropriate for the type and nature |
| * of the specific view transition. Can be one either ViewTransitionBase.ACTION_BAR_MODE_FADE, |
| * ViewTransitionBase.ACTION_BAR_MODE_FADE_AND_SLIDE, or null. If set to fade |
| * and slide, the actionBarTransitionDirection property is considered by the |
| * default createActionBarEffect() implementation. |
| * |
| * @default ACTION_BAR_MODE_FADE_AND_SLIDE |
| */ |
| mx_internal var actionBarTransitionMode:String = ACTION_BAR_MODE_FADE_AND_SLIDE; |
| |
| //---------------------------------- |
| // actionBarTransitionDirection |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Convenience property used by ViewTransitionBase overrides to hint the direction |
| * of the default action bar transition when the actionBarTransitionMode is set to |
| * "fadeAndSlide". Can be or null or set to one of the ViewTransitionDirection |
| * constants. This property is considered by the default createActionBarEffect() |
| * implementation. |
| * |
| * @default ViewTransitionDirection.LEFT |
| */ |
| mx_internal var actionBarTransitionDirection:String = ViewTransitionDirection.LEFT; |
| |
| //---------------------------------- |
| // cachedNavigatorSnapshot |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Cached image of the cumulative view of the owning navigator |
| * captured by the default captureStartValues() implementation. |
| * This snapshot is generally leveraged by transitions that need to |
| * performing a full screen transition. |
| */ |
| mx_internal var cachedNavigator:BitmapImage; |
| |
| /** |
| * @private |
| * Stores the location of the cached navigator in the global coordinate space |
| * so that the transition can properly position it when added to the display list. |
| */ |
| mx_internal var cachedNavigatorGlobalPosition:Point = new Point(); |
| |
| //---------------------------------- |
| // cachedActionGroupSnapshot |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Cached image of the action bar's action group. This image is |
| * only captured by default if action group content exists in the |
| * previous view. |
| */ |
| mx_internal var cachedActionGroup:BitmapImage; |
| |
| /** |
| * @private |
| * Stores the location of the cached navigator in the global coordinate space |
| * so that the transition can properly position it when added to the display list. |
| */ |
| mx_internal var cachedActionGroupGlobalPosition:Point = new Point(); |
| |
| //---------------------------------- |
| // cachedTitleGroupSnapshot |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Cached image of the action bar's title group. This image is |
| * only captured by default if title group content exists in the |
| * previous view. |
| */ |
| mx_internal var cachedTitleGroup:BitmapImage; |
| |
| /** |
| * @private |
| * Stores the location of the cached navigator in the global coordinate space |
| * so that the transition can properly position it when added to the display list. |
| */ |
| mx_internal var cachedTitleGroupGlobalPosition:Point = new Point(); |
| |
| //---------------------------------- |
| // cachedNavigationGroupSnapshot |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Cached image of the action bar's navigation group. This image is |
| * only captured by default if navigation group content exists in the |
| * previous view. |
| */ |
| mx_internal var cachedNavigationGroup:BitmapImage; |
| |
| /** |
| * @private |
| * Stores the location of the cached navigator in the global coordinate space |
| * so that the transition can properly position it when added to the display list. |
| */ |
| mx_internal var cachedNavigationGroupGlobalPosition:Point = new Point(); |
| |
| //---------------------------------- |
| // targetNavigator |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Convenience property which caches our primary containing navigator, |
| * this is usually our owning ViewNavigator but may be an outer TabNavigator |
| */ |
| protected var targetNavigator:ViewNavigatorBase; |
| |
| //---------------------------------- |
| // parentNavigator |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Convenience property which caches our primary containing navigator, |
| * this is usually our owning ViewNavigator but may be an outer TabNavigator |
| */ |
| protected var parentNavigator:ViewNavigatorBase; |
| |
| //---------------------------------- |
| // actionBar |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Convenience property which caches our associated action bar. |
| */ |
| protected var actionBar:ActionBar; |
| |
| /** |
| * @private |
| * Convenience property which caches our associated tab bar. |
| */ |
| protected var tabBar:ButtonBarBase; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| mx_internal function preInit():void |
| { |
| // Override |
| } |
| |
| /** |
| * Called by the ViewNavigator during the preparation phase of a transition. |
| * It is invoked when the new view has been fully realized and validated and the |
| * action bar and tab bar content reflect the state of the new view. |
| * The transition can use this method capture any values it requires from the |
| * pending view. |
| * Any bitmaps reflecting the state of the new view, tab bar, |
| * or action bar should be captured if required for animation. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function captureStartValues():void |
| { |
| // Remember some common references. |
| parentNavigator = navigator.parentNavigator; |
| |
| if (parentNavigator is TabbedViewNavigator) |
| { |
| targetNavigator = parentNavigator; |
| tabBar = TabbedViewNavigator(parentNavigator).tabBar; |
| } |
| else |
| { |
| targetNavigator = navigator; |
| } |
| |
| if (navigator) |
| actionBar = navigator.actionBar; |
| |
| // Determine first if we're able to transition our control bars independently |
| // of our view content. If we are, then capture the necessary action bar |
| // bitmap snapshots for use later by our default action bar transition. |
| if (!consolidatedTransition) |
| consolidatedTransition = !canTransitionControlBarContent(); |
| |
| // Snapshot component parts of action bar in preparation for our |
| // default action bar transition, (if appropriate). |
| if (!consolidatedTransition) |
| { |
| if (componentIsVisible(actionBar)) |
| { |
| // Save bounds of action bar. |
| cachedActionBarWidth = actionBar.width; |
| cachedActionBarHeight = actionBar.height; |
| |
| // Snapshot title content of our startView. |
| if (actionBar.titleGroup && actionBar.titleGroup.visible) |
| cachedTitleGroup = getSnapshot(actionBar.titleGroup, 4, cachedTitleGroupGlobalPosition); |
| else if (actionBar.titleDisplay |
| && (actionBar.titleDisplay is UIComponent) |
| && UIComponent(actionBar.titleDisplay).visible) |
| cachedTitleGroup = getSnapshot(UIComponent(actionBar.titleDisplay), 4, cachedTitleGroupGlobalPosition); |
| |
| // Snapshot actionContent if it's changing between our start and end views. |
| if (startView.actionContent != endView.actionContent) |
| cachedActionGroup = getSnapshot(actionBar.actionGroup, 4, cachedActionGroupGlobalPosition); |
| |
| // Snapshot navigationContent if it's changing between our start and end views. |
| if (startView.navigationContent != endView.navigationContent) |
| cachedNavigationGroup = getSnapshot(actionBar.navigationGroup, 4, cachedNavigationGroupGlobalPosition); |
| } |
| } |
| } |
| |
| /** |
| * Called by the ViewNavigator during the preparation phase of a transition. |
| * It is invoked when the new view has been fully realized and validated and the |
| * action bar and tab bar content reflect the state of the new view. |
| * It is at this point that the transition can capture any values it requires from the |
| * pending view. |
| * In addition any bitmaps reflecting the state of the new view, tab bar, |
| * or action bar should be captured, if required for animation. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function captureEndValues():void |
| { |
| // One final check to determine if we will be required to perform a full |
| // (consolidated) transition. |
| if (!consolidatedTransition && actionBar) |
| { |
| consolidatedTransition = |
| ((actionBar.height != cachedActionBarHeight) || |
| (actionBar.width != cachedActionBarWidth)); |
| } |
| } |
| |
| /** |
| * Called by the ViewNavigator when the transition |
| * should begin animating. |
| * At this time, the transition should dispatch a |
| * <code>start</code> event. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function play():void |
| { |
| if (effect) |
| { |
| activeTransitions.push(this); |
| effect.addEventListener(EffectEvent.EFFECT_END, effectComplete); |
| |
| // Dispatch TRANSITION_START. |
| if (hasEventListener(FlexEvent.TRANSITION_START)) |
| dispatchEvent(new FlexEvent(FlexEvent.TRANSITION_START)); |
| |
| if (navigator && navigator.stage && navigator.stage.hasEventListener(FlexEvent.TRANSITION_START)) |
| navigator.stage.dispatchEvent(new FlexEvent(FlexEvent.TRANSITION_START)); |
| |
| effect.play(); |
| } |
| else |
| transitionComplete(); |
| } |
| |
| /** |
| * Called by the ViewNavigator during the preparation phase |
| * of a transition. |
| * This method gives the transition the chance to create and |
| * configure the underlying IEffect instance, or to add any transient |
| * elements to the display list. |
| * Example transient elements include bitmap placeholders, temporary |
| * containers required during the transition, and other elements. |
| * If required, a final validation pass occurs prior to the invocation |
| * of the <code>play()</code> method. |
| * |
| * <p>If it is determined that a standard transition can be initiated, |
| * meaning one that transitions the control bars separately from the views, |
| * the default implementation of this method constructs |
| * a single Parallel effect which wraps the individual effect sequences |
| * for the view transition, the action bar transition, and the tab bar transition. |
| * This method uses the methods, <code>createActionBarEffect()</code>, |
| * <code>createTabBarEffect()</code>, and <code>createViewEffect()</code>.</p> |
| * |
| * <p>If <code>transitionControlsWithContent</code> is set to <code>true</code>, |
| * or if it is determined that the control bars cannot be transitioned independently, |
| * a single effect is created to transition the navigator in its entirety. |
| * In this case, only <code>createConsolidatedEffect()</code> is invoked.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function prepareForPlay():void |
| { |
| if (!consolidatedTransition) |
| { |
| effect = new Parallel(); |
| |
| // Prepare action bar effect |
| if (actionBar) |
| { |
| var actionBarEffect:IEffect = createActionBarEffect(); |
| if (actionBarEffect) |
| Parallel(effect).addChild(actionBarEffect); |
| } |
| |
| // Prepare tab bar effect |
| if (targetNavigator is TabbedViewNavigator) |
| { |
| if (TabbedViewNavigator(targetNavigator).tabBar) |
| { |
| var tabBarEffect:IEffect = createTabBarEffect(); |
| if (tabBarEffect) |
| Parallel(effect).addChild(tabBarEffect); |
| } |
| } |
| |
| // Prepare view effect |
| var viewEffect:IEffect = createViewEffect(); |
| if (viewEffect) |
| Parallel(effect).addChild(viewEffect); |
| } |
| else |
| { |
| // Prepare full transition of navigator in its entirety. |
| effect = createConsolidatedEffect(); |
| } |
| |
| // Disable layout manager if requested. |
| if (suspendBackgroundProcessing) |
| UIComponent.suspendBackgroundProcessing(); |
| } |
| |
| /** |
| * Called by the default <code>prepareForPlay()</code> implementation, |
| * this method is responsible for creating the Spark effect |
| * played on the action bar when the transition starts. |
| * This method should be overridden by subclasses if a custom action bar |
| * effect is required. |
| * By default, this method returns a basic action bar effect. |
| * |
| * @return An IEffect instance serving as the action bar effect. |
| * This effect is played by the default <code>play()</code> method implementation. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function createActionBarEffect():IEffect |
| { |
| var transformOffsets:TransformOffsets; |
| var slideDistance:Number; |
| var animatedProperty:String; |
| |
| var actionBarSkin:UIComponent = actionBar.skin; |
| var slideTargets:Array = []; |
| var fadeOutTargets:Array = []; |
| var fadeInTargets:Array = []; |
| |
| // Return if we have a noop action bar transition mode. |
| if (!actionBar || actionBarTransitionMode == ACTION_BAR_MODE_NONE || |
| !actionBarTransitionMode) |
| return null; |
| |
| transitionGroup = new Group(); |
| transitionGroup.autoLayout = false; |
| transitionGroup.includeInLayout = false; |
| transitionGroup.width = actionBar.width; |
| transitionGroup.height = actionBar.height; |
| addComponentToContainer(transitionGroup, actionBarSkin); |
| |
| // Construct our parallel effect. |
| var actionBarEffect:Parallel = new Parallel(); |
| |
| // Calculate the slide distance based on direction. |
| switch (actionBarTransitionDirection) |
| { |
| case ViewTransitionDirection.RIGHT: |
| animatedProperty = "x"; |
| slideDistance = -actionBar.width / 2.5; |
| break; |
| |
| case ViewTransitionDirection.DOWN: |
| animatedProperty = "y"; |
| slideDistance = -actionBar.height / 2.5; |
| verticalTransition = true; |
| break; |
| |
| case ViewTransitionDirection.UP: |
| animatedProperty = "y"; |
| slideDistance = actionBar.height / 2.5; |
| verticalTransition = true; |
| break; |
| |
| case ViewTransitionDirection.LEFT: |
| default: |
| animatedProperty = "x"; |
| slideDistance = actionBar.width / 2.5; |
| break; |
| } |
| |
| transitionGroup.clipAndEnableScrolling = true; |
| |
| // Suppress slide if our action bar transition behavior is fade-only. |
| if (actionBarTransitionMode == ACTION_BAR_MODE_FADE) |
| slideDistance = 0; |
| |
| // If the skin has title content queue new title content for fade in. |
| if (actionBar.titleGroup || actionBar.titleDisplay) |
| { |
| var titleComponent:UIComponent = actionBar.titleGroup; |
| |
| if (!titleComponent || !titleComponent.visible) |
| titleComponent = actionBar.titleDisplay as UIComponent; |
| |
| if (titleComponent) |
| { |
| // Initialize the transformation offests |
| transformOffsets = new TransformOffsets(); |
| transformOffsets[animatedProperty] = slideDistance; |
| slideTargets.push(transformOffsets); |
| |
| // Initialize titleGroup |
| titleComponent.cacheAsBitmap = true; |
| titleComponent.alpha = 0; |
| titleComponent.postLayoutTransformOffsets = transformOffsets; |
| fadeInTargets.push(titleComponent); |
| |
| // We reparent the titleComponent into the transition group so |
| // that the items are properly clipped when animating vertically |
| if (verticalTransition) |
| transitionGroup.addElementAt(titleComponent, 0); |
| } |
| |
| if (cachedTitleGroup) |
| addCachedElementToGroup(transitionGroup, cachedTitleGroup, cachedTitleGroupGlobalPosition); |
| } |
| |
| // If a cache of the navigation group exists, that means the content |
| // changed. In this case the queue cached representation to be faded |
| // out. |
| if (cachedNavigationGroup) |
| addCachedElementToGroup(transitionGroup, cachedNavigationGroup, cachedNavigationGroupGlobalPosition); |
| |
| // If a cache of the action group exists, that means the content |
| // changed. In this case the queue cached representation to be faded |
| // out. |
| if (cachedActionGroup) |
| addCachedElementToGroup(transitionGroup, cachedActionGroup, cachedActionGroupGlobalPosition); |
| |
| // Create fade in animations for navigationContent and actionContent |
| // of the next view. |
| if (endView) |
| { |
| if (endView.navigationContent) |
| { |
| // Initialize the transformation offests |
| transformOffsets = new TransformOffsets(); |
| transformOffsets[animatedProperty] = slideDistance; |
| slideTargets.push(transformOffsets); |
| |
| actionBar.navigationGroup.postLayoutTransformOffsets = transformOffsets; |
| actionBar.navigationGroup.cacheAsBitmap = true; |
| actionBar.navigationGroup.alpha = 0; |
| fadeInTargets.push(actionBar.navigationGroup); |
| |
| // We reparent the titleComponent into the transition group so |
| // that the items are properly clipped when animating vertically |
| if (verticalTransition) |
| transitionGroup.addElementAt(actionBar.navigationGroup, 0); |
| } |
| |
| if (endView.actionContent) |
| { |
| // Initialize the transformation offests |
| transformOffsets = new TransformOffsets(); |
| transformOffsets[animatedProperty] = slideDistance; |
| slideTargets.push(transformOffsets); |
| |
| actionBar.actionGroup.postLayoutTransformOffsets = transformOffsets; |
| actionBar.actionGroup.cacheAsBitmap = true; |
| actionBar.actionGroup.alpha = 0; |
| fadeInTargets.push(actionBar.actionGroup); |
| |
| // We reparent the titleComponent into the transition group so |
| // that the items are properly clipped when animating vertically |
| if (verticalTransition) |
| transitionGroup.addElementAt(actionBar.actionGroup, 0); |
| } |
| } |
| |
| // Ensure bitmaps are rendered prior to invocation of our effect. |
| transitionGroup.validateNow(); |
| |
| |
| // Setup fade out targets |
| if (cachedTitleGroup) |
| { |
| // Initialize the transformation offests |
| transformOffsets = new TransformOffsets(); |
| slideTargets.push(transformOffsets); |
| |
| cachedTitleGroup.postLayoutTransformOffsets = transformOffsets; |
| fadeOutTargets.push(cachedTitleGroup.displayObject); |
| } |
| |
| if (cachedNavigationGroup) |
| { |
| // Initialize the transformation offests |
| transformOffsets = new TransformOffsets(); |
| slideTargets.push(transformOffsets); |
| |
| cachedNavigationGroup.postLayoutTransformOffsets = transformOffsets; |
| fadeOutTargets.push(cachedNavigationGroup.displayObject); |
| } |
| |
| if (cachedActionGroup) |
| { |
| // Initialize the transformation offests |
| transformOffsets = new TransformOffsets(); |
| slideTargets.push(transformOffsets); |
| |
| cachedActionGroup.postLayoutTransformOffsets = transformOffsets; |
| fadeOutTargets.push(cachedActionGroup.displayObject); |
| } |
| |
| // If no fade effects we aren't animating anything so return null |
| if (fadeInTargets.length == 0 && fadeOutTargets.length == 0) |
| return null; |
| |
| // Create fade in effect |
| if (fadeInTargets.length > 0) |
| { |
| var fadeInEffect:Fade = new Fade(); |
| fadeInEffect.targets = fadeInTargets; |
| fadeInEffect.duration = duration; |
| fadeInEffect.alphaFrom = 0; |
| fadeInEffect.alphaTo = 1; |
| actionBarEffect.addChild(fadeInEffect); |
| } |
| |
| // Create fade out effect |
| if (fadeOutTargets.length > 0) |
| { |
| var fadeOutEffect:Fade = new Fade(); |
| fadeOutEffect.targets = fadeOutTargets; |
| fadeOutEffect.duration = duration; |
| fadeOutEffect.alphaFrom = 1; |
| fadeOutEffect.alphaTo = 0; |
| actionBarEffect.addChild(fadeOutEffect); |
| } |
| |
| // Create slide in effect |
| var vector:Vector.<MotionPath> = new Vector.<MotionPath>(); |
| vector.push(new SimpleMotionPath(animatedProperty, null, null, -slideDistance)); |
| |
| var moveEffect:Animate = new Animate(); |
| moveEffect.targets = slideTargets; |
| moveEffect.motionPaths = vector; |
| moveEffect.easer = new spark.effects.easing.Sine(.7); |
| moveEffect.duration = duration; |
| moveEffect.addEventListener(EffectEvent.EFFECT_UPDATE, actionBarMoveEffect_effectUpdateHandler); |
| moveEffect.addEventListener(EffectEvent.EFFECT_END, actionBarMoveEffect_effectEndedHandler); |
| actionBarEffect.addChild(moveEffect); |
| |
| return actionBarEffect; |
| } |
| |
| /** |
| * Called by the default <code>prepareForPlay()</code> implementation, |
| * this method is responsible for creating the Spark effect played |
| * on the tab bar when the transition starts. |
| * This method should be overridden by subclasses. |
| * By default, this returns null. |
| * |
| * @return An IEffect instance serving as the tab bar transition. |
| * This effect is played by the default <code>play()</code> method implementation. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function createTabBarEffect():IEffect |
| { |
| return null; |
| } |
| |
| /** |
| * Called by the default <code>prepareForPlay()</code> implementation, |
| * this method is responsible for creating the Spark effect played |
| * on the current and next view when the transition starts. |
| * This method should be overridden by subclasses. |
| * By default, this method returns null. |
| * |
| * @return An IEffect instance serving as the view transition. |
| * This effect is played by the default <code>play()</code> method implementation. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function createViewEffect():IEffect |
| { |
| return null; |
| } |
| |
| /** |
| * Called by the default <code>prepareForPlay()</code> implementation, |
| * this method is responsible for creating the Spark effect played to |
| * transition the entire navigator, inclusive of the control bar content, |
| * when necessary. |
| * This method should be overridden by subclasses. |
| * By default, this method returns null. |
| * |
| * @return An IEffect instance serving as the view transition. |
| * This effect is played by the default <code>play()</code> method implementation. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function createConsolidatedEffect():IEffect |
| { |
| return null; |
| } |
| |
| /** |
| * Called by the transition to indicate that the transition |
| * has completed. |
| * This method dispatches the <code>end</code> event. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function transitionComplete():void |
| { |
| var stage:Stage; |
| if (navigator) |
| stage = navigator.stage; |
| |
| cleanUp(); |
| |
| activeTransitions.splice(activeTransitions.indexOf(this), 1); |
| |
| if (hasEventListener(FlexEvent.TRANSITION_END)) |
| dispatchEvent(new FlexEvent(FlexEvent.TRANSITION_END)); |
| |
| if (stage && stage.hasEventListener(FlexEvent.TRANSITION_END)) |
| stage.dispatchEvent(new FlexEvent(FlexEvent.TRANSITION_END)); |
| } |
| |
| /** |
| * Called after the transition completes. |
| * This method is responsible for releasing any references |
| * and temporary constructs used by the transition. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function cleanUp():void |
| { |
| if (!consolidatedTransition && transitionGroup) |
| { |
| if (cachedTitleGroup) |
| transitionGroup.removeElement(cachedTitleGroup); |
| |
| if (cachedNavigationGroup) |
| transitionGroup.removeElement(cachedNavigationGroup); |
| |
| if (cachedActionGroup) |
| { |
| transitionGroup.removeElement(cachedActionGroup); |
| actionBar.actionGroup.cacheAsBitmap = false; |
| } |
| |
| if (actionBar) |
| { |
| // Restore title group and title content to their original state. |
| if (actionBar.titleGroup && actionBar.titleGroup.visible) |
| { |
| actionBar.titleGroup.postLayoutTransformOffsets = null; |
| actionBar.titleGroup.cacheAsBitmap = false; |
| } |
| |
| if (actionBar.titleDisplay |
| && (actionBar.titleDisplay is DisplayObject) |
| && DisplayObject(actionBar.titleDisplay).visible) |
| { |
| (actionBar.titleDisplay as UIComponent).postLayoutTransformOffsets = null; |
| DisplayObject(actionBar.titleDisplay).cacheAsBitmap = false; |
| } |
| |
| // Restore title group and title content to their original home. |
| if (verticalTransition) |
| { |
| var titleComponent:UIComponent = actionBar.titleGroup; |
| if (!titleComponent || !titleComponent.visible) |
| titleComponent = actionBar.titleDisplay as UIComponent; |
| |
| if (titleComponent) |
| { |
| transitionGroup.removeElement(titleComponent); |
| addComponentToContainer(titleComponent, actionBar.skin); |
| } |
| } |
| |
| // Restore navigation group to their proper home. |
| if (endView.navigationContent && verticalTransition) |
| { |
| transitionGroup.removeElement(actionBar.navigationGroup); |
| if (actionBar.titleDisplay) |
| { |
| var childIndex:uint = actionBar.skin.getChildIndex(actionBar.titleDisplay as DisplayObject); |
| addComponentToContainerAt(actionBar.navigationGroup, actionBar.skin, childIndex); |
| } |
| else |
| addComponentToContainer(actionBar.navigationGroup, actionBar.skin); |
| } |
| |
| // Restore action group to their proper home. |
| if (endView.actionContent && verticalTransition) |
| { |
| transitionGroup.removeElement(actionBar.actionGroup); |
| if (actionBar.titleDisplay) |
| { |
| childIndex = actionBar.skin.getChildIndex(actionBar.titleDisplay as DisplayObject); |
| addComponentToContainerAt(actionBar.actionGroup, actionBar.skin, childIndex); |
| } |
| else |
| addComponentToContainer(actionBar.actionGroup, actionBar.skin); |
| } |
| |
| removeComponentFromContainer(transitionGroup, actionBar.skin); |
| |
| actionBar.skin.scrollRect = null; |
| |
| // Force actionBar to update content group positions after |
| // animating positions. If the width and height change during |
| // the transition, we need relayout it's children because |
| // during the transition they are removed from layout and |
| // missed during the validation pass. See SDK-30142. |
| // TODO (jasonsj): Consider ending transitions when orientation |
| // changes |
| if ((actionBar.width != cachedActionBarWidth) |
| || (actionBar.height != cachedActionBarHeight)) |
| { |
| actionBar.skin.invalidateDisplayList(); |
| } |
| |
| if (actionBar.actionGroup) |
| actionBar.actionGroup.postLayoutTransformOffsets = null; |
| |
| if (actionBar.navigationGroup) |
| actionBar.navigationGroup.postLayoutTransformOffsets = null; |
| } |
| |
| verticalTransition = false; |
| cachedActionBarHeight = 0; |
| cachedActionBarWidth = 0; |
| |
| transitionGroup = null; |
| cachedTitleGroup = null; |
| cachedNavigationGroup = null; |
| cachedActionGroup = null; |
| } |
| |
| consolidatedTransition = false; |
| actionBar = null; |
| tabBar = null; |
| parentNavigator = null; |
| targetNavigator = null; |
| navigator = null; |
| startView = null; |
| endView = null; |
| |
| // Re-enable layout manager if appropriate. |
| if (suspendBackgroundProcessing) |
| UIComponent.resumeBackgroundProcessing(); |
| } |
| |
| /** |
| * Determine if Flex can perform a transition on |
| * action bar or tab bar content independently of the views. |
| * |
| * <p>Flex cannot perform a transition on the control bars independently:</p> |
| * <ul> |
| * <li>If the containing view navigator is a TabbedViewNavigator |
| * and its tab bar's visibility changes between views.</li> |
| * <li>If the value of the view navigator's <code>overlayControls</code> |
| * property changes between views.</li> |
| * <li>If the size or visibility of the action bar changes |
| * between views.</li> |
| * </ul> |
| * |
| * @return <code>false</code> if Flex determines controls bars between views are |
| * incompatible in some way. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function canTransitionControlBarContent():Boolean |
| { |
| // Short circuit if we've already been asked to not consider |
| // control bars during transition. |
| if (transitionControlsWithContent) |
| return false; |
| |
| // Test for visibility or size of tab bar changing. |
| if (targetNavigator is TabbedViewNavigator) |
| { |
| var tabBar:ButtonBarBase = TabbedViewNavigator(targetNavigator).tabBar; |
| if (componentIsVisible(tabBar) != endView.tabBarVisible) |
| return false; |
| } |
| |
| // Test for visibility or size of action bar changing. |
| if (navigator is ViewNavigator) |
| { |
| var actionBar:ActionBar = ViewNavigator(navigator).actionBar; |
| if (componentIsVisible(actionBar) != endView.actionBarVisible) |
| return false; |
| } |
| |
| // Test for valid views. |
| if (!startView || !endView) |
| return false; |
| |
| // Test for value of overlayControls changing. |
| if (startView.overlayControls != endView.overlayControls) |
| return false; |
| |
| return true; |
| } |
| |
| /** |
| * Used to render snap shots of screen elements in |
| * preparation for transitioning. |
| * The bitmap is returned in the form of a BitmapImage object. |
| * |
| * <p>The BitmapImage is in target's parent coordiantes space - |
| * it overlaps the target precisely if paranted to the same parent. |
| * |
| * When moving to a different parent, make sure to adjust the |
| * transformation of the BitmapImage to correctly account for the |
| * change in coordinate spaces. |
| * |
| * The updated value of the <code>globalPosition</code> parameter |
| * can be used for that.</p> |
| * |
| * @param target Display object to capture. |
| * |
| * @param padding Padding around the object to be included in |
| * the BitmapImage object. |
| * |
| * @param globalPosition When non-null, <code>globalPosition</code> |
| * will be updated with the origin of the BitmapImage in global |
| * coordiantes. When moving to a different coordinate space, this |
| * value can be used to adjust the snapshot's position so its |
| * global position on screen doesn't change. |
| * |
| * @return BitmapImage object representing the target. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| protected function getSnapshot(target:UIComponent, padding:int = 4, globalPosition:Point = null):BitmapImage |
| { |
| if (!target || !target.visible || target.width == 0 || target.height == 0) |
| return null; |
| |
| var snapshot:BitmapImage = new BitmapImage(); |
| |
| // Ensure bitmap leverages its own display object for performance |
| // reasons. |
| snapshot.alwaysCreateDisplayObject = true; |
| |
| // Capture image, with consideration for transform and color matrix. |
| // Return null if an error is thrown. |
| var bounds:Rectangle = new Rectangle(); |
| try |
| { |
| snapshot.source = BitmapUtil.getSnapshotWithPadding(target, padding, true, bounds); |
| } |
| catch (e:SecurityError) |
| { |
| return null; |
| } |
| |
| // Size and offset snapShot to match our image bounds data. |
| snapshot.width = bounds.width; |
| snapshot.height = bounds.height; |
| |
| var m:Matrix = new Matrix(); |
| m.translate(bounds.left, bounds.top); |
| |
| // Apply target's inverse concatenated matrix: |
| var parent:DisplayObjectContainer = target.parent; |
| if (parent) |
| { |
| var inverted:Matrix = parent.transform.concatenatedMatrix.clone(); |
| inverted.invert(); |
| m.concat(inverted); |
| } |
| snapshot.setLayoutMatrix(m, false); |
| |
| // Exclude from layout. |
| snapshot.includeInLayout = false; |
| |
| if (globalPosition) |
| { |
| var pt:Point = parent ? parent.localToGlobal(new Point(snapshot.x, snapshot.y)) : new Point(); |
| globalPosition.x = pt.x; |
| globalPosition.y = pt.y; |
| } |
| |
| return snapshot; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Private Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Remove listeners |
| */ |
| private function actionBarMoveEffect_effectEndedHandler(event:EffectEvent):void |
| { |
| event.target.removeEventListener(EffectEvent.EFFECT_UPDATE, actionBarMoveEffect_effectUpdateHandler); |
| event.target.removeEventListener(EffectEvent.EFFECT_END, actionBarMoveEffect_effectEndedHandler); |
| } |
| |
| /** |
| * @private |
| * Since layout is disabled, we need to force validation on all of the |
| * participating display objects. |
| */ |
| private function actionBarMoveEffect_effectUpdateHandler(event:EffectEvent):void |
| { |
| if (!actionBar) |
| return; |
| |
| // This code is a temporary performance fix for transitions. Since layout is |
| // disabled during ViewTransitions, in the past this method would call |
| // validateDisplayList() on the animation targets to update their internal position |
| // matrices. We learned that this was causing a reduction in framerate due to |
| // actionScript overhead. To workaround the issue we are moving the x and y positions |
| // of the underlying displayObjects manually. This is a temporary fix to get |
| // our performance numbers back up after checking in a fix for SDK-30839. |
| // TODO (chiedozi): Clean up this code and use propery layout methods |
| if (verticalTransition) |
| { |
| if (actionBar.actionGroup && actionBar.actionGroup.postLayoutTransformOffsets) |
| actionBar.actionGroup.$y = actionBar.actionGroup.y + actionBar.actionGroup.postLayoutTransformOffsets.y; |
| |
| if (actionBar.navigationGroup && actionBar.navigationGroup.postLayoutTransformOffsets) |
| actionBar.navigationGroup.$y = actionBar.navigationGroup.y + actionBar.navigationGroup.postLayoutTransformOffsets.y; |
| |
| if (actionBar.titleDisplay && UIComponent(actionBar.titleDisplay).postLayoutTransformOffsets) |
| UIComponent(actionBar.titleDisplay).$y = UIComponent(actionBar.titleDisplay).y + UIComponent(actionBar.titleDisplay).postLayoutTransformOffsets.y; |
| |
| if (actionBar.titleGroup && actionBar.titleGroup.postLayoutTransformOffsets) |
| actionBar.titleGroup.$y = actionBar.titleGroup.y + actionBar.titleGroup.postLayoutTransformOffsets.y; |
| |
| if (cachedTitleGroup && cachedTitleGroup.displayObject) |
| cachedTitleGroup.displayObject.y = cachedTitleGroup.y + cachedTitleGroup.postLayoutTransformOffsets.y; |
| |
| if (cachedNavigationGroup && cachedNavigationGroup.displayObject) |
| cachedNavigationGroup.displayObject.y = cachedNavigationGroup.y + cachedNavigationGroup.postLayoutTransformOffsets.y; |
| |
| if (cachedActionGroup && cachedActionGroup.displayObject) |
| cachedActionGroup.displayObject.y = cachedActionGroup.y + cachedActionGroup.postLayoutTransformOffsets.y; |
| } |
| else |
| { |
| if (actionBar.actionGroup && actionBar.actionGroup.postLayoutTransformOffsets) |
| actionBar.actionGroup.$x = actionBar.actionGroup.x + actionBar.actionGroup.postLayoutTransformOffsets.x; |
| |
| if (actionBar.navigationGroup && actionBar.navigationGroup.postLayoutTransformOffsets) |
| actionBar.navigationGroup.$x = actionBar.navigationGroup.x + actionBar.navigationGroup.postLayoutTransformOffsets.x; |
| |
| if (actionBar.titleDisplay && UIComponent(actionBar.titleDisplay).postLayoutTransformOffsets) |
| UIComponent(actionBar.titleDisplay).$x = UIComponent(actionBar.titleDisplay).x + UIComponent(actionBar.titleDisplay).postLayoutTransformOffsets.x; |
| |
| if (actionBar.titleGroup && actionBar.titleGroup.postLayoutTransformOffsets) |
| actionBar.titleGroup.$x = actionBar.titleGroup.x + actionBar.titleGroup.postLayoutTransformOffsets.x; |
| |
| if (cachedTitleGroup && cachedTitleGroup.displayObject) |
| cachedTitleGroup.displayObject.x = cachedTitleGroup.x + cachedTitleGroup.postLayoutTransformOffsets.x; |
| |
| if (cachedNavigationGroup && cachedNavigationGroup.displayObject) |
| cachedNavigationGroup.displayObject.x = cachedNavigationGroup.x + cachedNavigationGroup.postLayoutTransformOffsets.x; |
| |
| if (cachedActionGroup && cachedActionGroup.displayObject) |
| cachedActionGroup.displayObject.x = cachedActionGroup.x + cachedActionGroup.postLayoutTransformOffsets.x; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function effectComplete(event:EffectEvent):void |
| { |
| effect.removeEventListener(EffectEvent.EFFECT_END, effectComplete); |
| |
| // Validate the last frame of the actionBar animation so that it |
| // renders properly. We put this here because layout isn't reenabled |
| // until the next frame, meaning this validation won't be applied for |
| // two frames. |
| if (!consolidatedTransition) |
| actionBarMoveEffect_effectUpdateHandler(null); |
| |
| if (renderLastFrame) |
| { |
| // We don't call transitionComplete just yet, we want to ensure |
| // that the last frame of animation actually gets rendered on screen |
| // before we clean up after ourselves. This prevents a perceived |
| // stutter on the very last frame. |
| navigator.addEventListener(Event.ENTER_FRAME, enterFrameHandler); |
| } |
| else |
| { |
| enterFrameHandler(null); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function enterFrameHandler(event:Event):void |
| { |
| if (event) |
| navigator.removeEventListener(Event.ENTER_FRAME, enterFrameHandler); |
| |
| effect = null; |
| transitionComplete(); |
| } |
| |
| /** |
| * @private |
| * Helper method to test whether a component is visible to user. |
| */ |
| mx_internal function componentIsVisible(component:UIComponent):Boolean |
| { |
| return component && component.visible && |
| component.width && component.height && component.alpha; |
| } |
| |
| /** |
| * @private |
| * Helper method to add a UIComponent instance to either an IVisualElementContainer |
| * or DisplayObjectContainer. |
| */ |
| mx_internal function addComponentToContainerAt(component:UIComponent, |
| container:UIComponent, |
| index:int):void |
| { |
| if (container is IVisualElementContainer) |
| IVisualElementContainer(container).addElementAt(component, index); |
| else |
| container.addChildAt(component, index); |
| } |
| |
| /** |
| * @private |
| * Helper method to add a UIComponent instance to either an IVisualElementContainer |
| * or DisplayObjectContainer. |
| */ |
| mx_internal function addComponentToContainer(component:UIComponent, |
| container:UIComponent):void |
| { |
| if (container is IVisualElementContainer) |
| IVisualElementContainer(container).addElement(component); |
| else |
| container.addChild(component); |
| } |
| |
| /** |
| * @private |
| * Helper method to remove a UIComponent instance from either an IVisualElementContainer |
| * or DisplayObjectContainer. |
| */ |
| mx_internal function removeComponentFromContainer(component:UIComponent, |
| container:UIComponent):void |
| { |
| if (container is IVisualElementContainer) |
| IVisualElementContainer(container).removeElement(component); |
| else |
| container.removeChild(component); |
| } |
| |
| /** |
| * @private |
| * Helper method to set the child index of the given component. |
| */ |
| mx_internal function setComponentChildIndex(component:UIComponent, |
| container:UIComponent, |
| index:int):void |
| { |
| if (container is IVisualElementContainer) |
| IVisualElementContainer(container).setElementIndex(component, index); |
| else |
| container.setChildIndex(component, index); |
| } |
| |
| /** |
| * @private |
| * Adds the element to the targetGroup and adjusts the position |
| * so that the global position remains the same. |
| * |
| * Note the targetGroup must be already added to the display list and |
| * positioned in order for this method to adjust the cachedElement's position |
| * correctly. |
| * |
| * @param targetGroup The Group that will parent the cached element. |
| * @param cachedElement The cached element - the return value of getSnapshot() |
| * @param cachedElementGlobalPosition The global position returned from getSnapshot() |
| * |
| * @see #getSnapshot |
| */ |
| mx_internal function addCachedElementToGroup(targetGroup:Group, |
| cachedElement:BitmapImage, |
| cachedElementGlobalPosition:Point):void |
| { |
| targetGroup.addElement(cachedElement); |
| |
| // We are moving the cachedTitleGroup to the transitionGroup's coordinate space, |
| // adjust the position |
| var localOrigin:Point = targetGroup.globalToLocal(cachedElementGlobalPosition); |
| cachedElement.x = localOrigin.x; |
| cachedElement.y = localOrigin.y; |
| } |
| |
| /** |
| * @private |
| * Helper method that returns index of the given component. |
| */ |
| mx_internal function getComponentChildIndex(component:UIComponent, container:UIComponent):int |
| { |
| if (container is IVisualElementContainer) |
| return IVisualElementContainer(container).getElementIndex(component); |
| else |
| return container.getChildIndex(component); |
| } |
| } |
| } |