| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 mx.effects |
| { |
| |
| import flash.events.Event; |
| import flash.events.EventDispatcher; |
| |
| import mx.core.FlexVersion; |
| import mx.core.IFlexDisplayObject; |
| import mx.core.mx_internal; |
| import mx.effects.effectClasses.AddRemoveEffectTargetFilter; |
| import mx.effects.effectClasses.HideShowEffectTargetFilter; |
| import mx.effects.effectClasses.PropertyChanges; |
| import mx.events.EffectEvent; |
| import mx.managers.LayoutManager; |
| import mx.styles.IStyleClient; |
| import mx.utils.NameUtil; |
| |
| use namespace mx_internal; |
| |
| /** |
| * Dispatched when one of the effect's instances finishes playing, |
| * either when the instance finishes playing or when the effect |
| * is interrupted by a call to the <code>end()</code> method. |
| * |
| * @eventType mx.events.EffectEvent.EFFECT_END |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="effectEnd", type="mx.events.EffectEvent")] |
| |
| /** |
| * Dispatched when the effect has been stopped, |
| * which only occurs when the effect is |
| * interrupted by a call to the <code>stop()</code> method. |
| * The EFFECT_END event is also dispatched to indicate that |
| * the effect has ended. This extra event is sent first, as an |
| * indicator to listeners that the effect did not reach its |
| * end state. |
| * |
| * @eventType mx.events.EffectEvent.EFFECT_STOP |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="effectStop", type="mx.events.EffectEvent")] |
| |
| /** |
| * Dispatched when the effect starts playing. |
| * |
| * @eventType mx.events.EffectEvent.EFFECT_START |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="effectStart", type="mx.events.EffectEvent")] |
| |
| /** |
| * The Effect class is an abstract base class that defines the basic |
| * functionality of all Flex effects. |
| * The Effect class defines the base factory class for all effects. |
| * The EffectInstance class defines the base class for all effect |
| * instance subclasses. |
| * |
| * <p>You do not create an instance of the Effect class itself |
| * in an application. |
| * Instead, you create an instance of one of the subclasses, |
| * such as Fade or WipeLeft.</p> |
| * |
| * @mxml |
| * |
| * <p>The Effect class defines the following properties, |
| * which all of its subclasses inherit:</p> |
| * |
| * <pre> |
| * <mx:<i>tagname</i> |
| * <b>Properties</b> |
| * customFilter="" |
| * duration="500" |
| * filter="" |
| * hideFocusRing="false" |
| * perElementOffset="0" |
| * repeatCount="1" |
| * repeatDelay="0" |
| * startDelay="0" |
| * suspendBackgroundProcessing="false|true" |
| * target="<i>effect target</i>" |
| * targets="<i>array of effect targets</i>" |
| * |
| * <b>Events</b> |
| * effectEnd="<i>No default</i>" |
| * efectStart="<i>No default</i>" |
| * /> |
| * </pre> |
| * |
| * @see mx.effects.EffectInstance |
| * |
| * @includeExample examples/SimpleEffectExample.mxml |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class Effect extends EventDispatcher implements IEffect |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static function mergeArrays(a1:Array, a2:Array):Array |
| { |
| if (a2) |
| { |
| for (var i2:int = 0; i2 < a2.length; i2++) |
| { |
| var addIt:Boolean = true; |
| |
| for (var i1:int = 0; i1 < a1.length; i1++) |
| { |
| if (a1[i1] == a2[i2]) |
| { |
| addIt = false; |
| break; |
| } |
| } |
| |
| if (addIt) |
| a1.push(a2[i2]); |
| } |
| } |
| |
| return a1; |
| } |
| |
| /** |
| * @private |
| */ |
| private static function stripUnchangedValues(propChanges:Array):Array |
| { |
| // Go through and remove any before/after values that are the same. |
| for (var i:int = 0; i < propChanges.length; i++) |
| { |
| if (propChanges[i].stripUnchangedValues == false) |
| continue; |
| |
| for (var prop:Object in propChanges[i].start) |
| { |
| if ((propChanges[i].start[prop] == |
| propChanges[i].end[prop]) || |
| (typeof(propChanges[i].start[prop]) == "number" && |
| typeof(propChanges[i].end[prop])== "number" && |
| isNaN(propChanges[i].start[prop]) && |
| isNaN(propChanges[i].end[prop]))) |
| { |
| delete propChanges[i].start[prop]; |
| delete propChanges[i].end[prop]; |
| } |
| } |
| } |
| |
| return propChanges; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * <p>Starting an effect is usually a three-step process:</p> |
| * |
| * <ul> |
| * <li>Create an instance of the effect object |
| * with the <code>new</code> operator.</li> |
| * <li>Set properties on the effect object, |
| * such as <code>duration</code>.</li> |
| * <li>Call the <code>play()</code> method |
| * or assign the effect to a trigger.</li> |
| * </ul> |
| * |
| * @param target The Object to animate with this effect. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function Effect(target:Object = null) |
| { |
| super(); |
| |
| this.target = target; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| // Transitions will force the values animated by this effect to get set to |
| // their final values, as specified in the end state, when the effect finishes. |
| // This flag is set to true when the effect is being played by a transition, |
| // but applying the values is still gated by the value of the |
| // applyTransitionEndProperties flag, which is set on a per-Effect basis. |
| mx_internal var applyEndValuesWhenDone:Boolean = false; |
| |
| // This property tracks whether the effect is playing in interruption mode. |
| // Normally, effects pick up starting values (when not provided explicitly) |
| // from the current values of the target objects. But when playing in interruption |
| // mode, the effect should get its starting values from the propertyChanges |
| // array instead. |
| private var _transitionInterruption:Boolean = false; |
| |
| mx_internal function get transitionInterruption():Boolean |
| { |
| return _transitionInterruption; |
| } |
| mx_internal function set transitionInterruption(value:Boolean):void |
| { |
| _transitionInterruption = value; |
| } |
| |
| // This is new behavior for the Flex4 effects; previously, we would not |
| // set the end-state values automatically. Because of this switch, the |
| // default value is hinged on a compatibility check, so that applications |
| // can choose to have the older behavior instead. |
| /** |
| * This flag controls whether the effect, when run in a transition, |
| * automatically applies the property values according to the end |
| * state, as opposed to leaving values as set by the effect itself. |
| * |
| * @default true |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected var applyTransitionEndProperties:Boolean = |
| (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_0) ? |
| false : true; |
| |
| /** |
| * @private |
| */ |
| private var _instances:Array /* of EffectInstance */ = []; |
| |
| /** |
| * @private |
| */ |
| private var _callValidateNow:Boolean = false; |
| |
| /** |
| * @private |
| */ |
| private var isPaused:Boolean = false; |
| |
| /** |
| * @private |
| */ |
| mx_internal var filterObject:EffectTargetFilter; |
| |
| /** |
| * @private |
| * Used in applyValueToTarget() |
| */ |
| mx_internal var applyActualDimensions:Boolean = true; |
| |
| /** |
| * @private |
| * Holds the init object passed in by the Transition. |
| */ |
| mx_internal var propertyChangesArray:Array; |
| |
| /** |
| * @private |
| * Track the property set in the play() function |
| */ |
| mx_internal var playReversed:Boolean; |
| |
| private var effectStopped:Boolean; |
| |
| /** |
| * @private |
| * Pointer back to the CompositeEffect that created this instance. |
| * Value is null if we are not the child of a CompositeEffect |
| */ |
| mx_internal var parentCompositeEffect:Effect; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // className |
| //---------------------------------- |
| |
| /** |
| * @copy mx.effects.IEffect#className |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get className():String |
| { |
| return NameUtil.getUnqualifiedClassName(this); |
| } |
| |
| //---------------------------------- |
| // customFilter |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the customFilter property. |
| */ |
| private var _customFilter:EffectTargetFilter; |
| |
| /** |
| * @copy mx.effects.IEffect#customFilter |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get customFilter():EffectTargetFilter |
| { |
| return _customFilter; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set customFilter(value:EffectTargetFilter):void |
| { |
| _customFilter = value; |
| filterObject = value; |
| } |
| |
| //---------------------------------- |
| // duration |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the duration property. |
| */ |
| private var _duration:Number = 500; |
| |
| /** |
| * @private |
| */ |
| mx_internal var durationExplicitlySet:Boolean = false; |
| |
| [Inspectable(category="General", defaultValue="500", minValue="0.0")] |
| |
| /** |
| * @copy mx.effects.IEffect#duration |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get duration():Number |
| { |
| if (!durationExplicitlySet && |
| parentCompositeEffect) |
| { |
| return parentCompositeEffect.duration; |
| } |
| else |
| { |
| return _duration; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| public function set duration(value:Number):void |
| { |
| durationExplicitlySet = true; |
| _duration = value; |
| } |
| |
| //---------------------------------- |
| // effectTargetHost |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the effectTargetHost property. |
| */ |
| private var _effectTargetHost:IEffectTargetHost; |
| |
| /** |
| * @copy mx.effects.IEffect#effectTargetHost |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get effectTargetHost():IEffectTargetHost |
| { |
| return _effectTargetHost; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set effectTargetHost(value:IEffectTargetHost):void |
| { |
| _effectTargetHost = value; |
| } |
| |
| //---------------------------------- |
| // endValuesCaptured |
| //---------------------------------- |
| |
| /** |
| * A flag containing <code>true</code> if the end values |
| * of an effect have already been determined, |
| * or <code>false</code> if they should be acquired from the |
| * current properties of the effect targets when the effect runs. |
| * This property is required by data effects because the sequence |
| * of setting up the data effects, such as DefaultListEffect |
| * and DefaultTileListEffect, is more complicated than for |
| * normal effects. |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected var endValuesCaptured:Boolean = false; |
| |
| //---------------------------------- |
| // filter |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the filter property. |
| */ |
| private var _filter:String; |
| |
| [Inspectable(category="General", enumeration="add,remove,show,hide,move,resize,addItem,removeItem,replacedItem,replacementItem,none", defaultValue="none")] |
| |
| /** |
| * @copy mx.effects.IEffect#filter |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get filter():String |
| { |
| return _filter; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set filter(value:String):void |
| { |
| if (!customFilter) |
| { |
| _filter = value; |
| |
| switch (value) |
| { |
| case "add": |
| case "remove": |
| { |
| filterObject = |
| new AddRemoveEffectTargetFilter(); |
| AddRemoveEffectTargetFilter(filterObject).add = |
| (value == "add"); |
| break; |
| } |
| |
| case "hide": |
| case "show": |
| { |
| filterObject = |
| new HideShowEffectTargetFilter(); |
| HideShowEffectTargetFilter(filterObject).show = |
| (value == "show"); |
| break; |
| } |
| |
| case "move": |
| { |
| filterObject = |
| new EffectTargetFilter(); |
| filterObject.filterProperties = |
| [ "x", "y" ]; |
| break; |
| } |
| |
| case "resize": |
| { |
| filterObject = |
| new EffectTargetFilter(); |
| filterObject.filterProperties = |
| [ "width", "height" ]; |
| break; |
| } |
| |
| case "addItem": |
| { |
| filterObject = new EffectTargetFilter(); |
| filterObject.requiredSemantics = {added:true}; |
| break; |
| } |
| |
| case "removeItem": |
| { |
| filterObject = new EffectTargetFilter(); |
| filterObject.requiredSemantics = {removed:true}; |
| break; |
| } |
| |
| case "replacedItem": |
| { |
| filterObject = new EffectTargetFilter(); |
| filterObject.requiredSemantics = {replaced:true}; |
| break; |
| } |
| |
| case "replacementItem": |
| { |
| filterObject = new EffectTargetFilter(); |
| filterObject.requiredSemantics = {replacement:true}; |
| break; |
| } |
| |
| default: |
| { |
| filterObject = null; |
| break; |
| } |
| } |
| } |
| } |
| |
| //---------------------------------- |
| // hideFocusRing |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the hideFocusRing property. |
| */ |
| private var _hideFocusRing:Boolean = false; |
| |
| /** |
| * @copy mx.effects.IEffect#hideFocusRing |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get hideFocusRing():Boolean |
| { |
| return _hideFocusRing; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set hideFocusRing(value:Boolean):void |
| { |
| _hideFocusRing = value; |
| } |
| |
| //---------------------------------- |
| // instanceClass |
| //---------------------------------- |
| |
| /** |
| * An object of type Class that specifies the effect |
| * instance class class for this effect class. |
| * |
| * <p>All subclasses of the Effect class must set this property |
| * in their constructor.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var instanceClass:Class = IEffectInstance; |
| |
| |
| //---------------------------------- |
| // isPlaying |
| //---------------------------------- |
| |
| /** |
| * @copy mx.effects.IEffect#isPlaying |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get isPlaying():Boolean |
| { |
| return _instances && _instances.length > 0; |
| } |
| |
| //---------------------------------- |
| // perElementOffset |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the perElementOffset property. |
| */ |
| private var _perElementOffset:Number = 0; |
| |
| [Inspectable(defaultValue="0", category="General", verbose="0", minValue="0.0")] |
| |
| /** |
| * @copy mx.effects.IEffect#perElementOffset |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get perElementOffset():Number |
| { |
| return _perElementOffset; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set perElementOffset(value:Number):void |
| { |
| _perElementOffset = value; |
| } |
| |
| //---------------------------------- |
| // relevantProperties |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the relevantProperties property. |
| */ |
| private var _relevantProperties:Array /* of String */; |
| |
| /** |
| * @copy mx.effects.IEffect#relevantProperties |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get relevantProperties():Array /* of String */ |
| { |
| if (_relevantProperties) |
| return _relevantProperties; |
| else |
| return getAffectedProperties(); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set relevantProperties(value:Array /* of String */):void |
| { |
| _relevantProperties = value; |
| } |
| |
| //---------------------------------- |
| // relevantStyles |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the relevantStyles property. |
| */ |
| private var _relevantStyles:Array /* of String */ = []; |
| |
| /** |
| * @copy mx.effects.IEffect#relevantStyles |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get relevantStyles():Array /* of String */ |
| { |
| return _relevantStyles; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set relevantStyles(value:Array /* of String */):void |
| { |
| _relevantStyles = value; |
| } |
| |
| //---------------------------------- |
| // repeatCount |
| //---------------------------------- |
| |
| [Inspectable(category="General", defaultValue="1", minValue="0")] |
| |
| /** |
| * Number of times to repeat the effect. |
| * Possible values are any integer greater than or equal to 0. |
| * A value of 1 means to play the effect once. |
| * A value of 0 means to play the effect indefinitely |
| * until stopped by a call to the <code>end()</code> method. |
| * |
| * @default 1 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var repeatCount:int = 1; |
| |
| |
| //---------------------------------- |
| // repeatDelay |
| //---------------------------------- |
| |
| [Inspectable(category="General", defaultValue="0", minValue="0")] |
| |
| /** |
| * Amount of time, in milliseconds, to wait before repeating the effect. |
| * Possible values are any integer greater than or equal to 0. |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var repeatDelay:int = 0; |
| |
| |
| //---------------------------------- |
| // startDelay |
| //---------------------------------- |
| |
| [Inspectable(category="General", defaultValue="0", minValue="0")] |
| |
| /** |
| * Amount of time, in milliseconds, to wait before starting the effect. |
| * Possible values are any int greater than or equal to 0. |
| * If the effect is repeated by using the <code>repeatCount</code> |
| * property, the <code>startDelay</code> is only applied |
| * to the first time the effect is played. |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var startDelay:int = 0; |
| |
| //---------------------------------- |
| // suspendBackgroundProcessing |
| //---------------------------------- |
| |
| /** |
| * If <code>true</code>, blocks all background processing |
| * while the effect is playing. |
| * Background processing includes measurement, layout, and |
| * processing responses that have arrived from the server. |
| * The default value is <code>false</code>. |
| * |
| * <p>You are encouraged to set this property to |
| * <code>true</code> in most cases, because it improves |
| * the performance of the application. |
| * However, the property should be set to <code>false</code> |
| * if either of the following is true:</p> |
| * <ul> |
| * <li>User input can arrive while the effect is playing, |
| * and the application must respond to the user input |
| * before the effect finishes playing.</li> |
| * <li>A response can arrive from the server while the effect |
| * is playing, and the application must process the response |
| * while the effect is still playing.</li> |
| * </ul> |
| * |
| * @default false |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public var suspendBackgroundProcessing:Boolean = false; |
| |
| |
| //---------------------------------- |
| // target |
| //---------------------------------- |
| |
| /** |
| * @copy mx.effects.IEffect#target |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get target():Object |
| { |
| if (_targets.length > 0) |
| return _targets[0]; |
| else |
| return null; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set target(value:Object):void |
| { |
| _targets.splice(0); |
| |
| if (value) |
| _targets[0] = value; |
| } |
| |
| //---------------------------------- |
| // targets |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the targets property. |
| */ |
| private var _targets:Array = []; |
| |
| [Inspectable(arrayType="Object")] |
| [ArrayElementType("Object")] |
| |
| /** |
| * @copy mx.effects.IEffect#targets |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get targets():Array |
| { |
| return _targets; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set targets(value:Array):void |
| { |
| // Strip out null values. |
| // Binding will trigger again when the null targets are created. |
| var n:int = value.length; |
| for (var i:int = n - 1; i >= 0; i--) |
| { |
| if (value[i] == null) |
| value.splice(i,1); |
| } |
| |
| _targets = value; |
| } |
| |
| //---------------------------------- |
| // triggerEvent |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the triggerEvent property. |
| */ |
| private var _triggerEvent:Event; |
| |
| /** |
| * @copy mx.effects.IEffect#triggerEvent |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get triggerEvent():Event |
| { |
| return _triggerEvent; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set triggerEvent(value:Event):void |
| { |
| _triggerEvent = value; |
| } |
| |
| //---------------------------------- |
| // playheadTime |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Backing storage for the playheadTime property. Note that this |
| * value is just a backup, used if the effect is not currently running. |
| * A running effect will query its effect instance for the value |
| * instead. |
| */ |
| private var _playheadTime:Number = 0; |
| |
| [Inspectable(minValue="0.0")] |
| |
| /** |
| * Current time position of the effect. |
| * This property has a value between 0 and the total duration, |
| * which includes the Effect's <code>startDelay</code>, |
| * <code>repeatCount</code>, and <code>repeatDelay</code>. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get playheadTime():Number |
| { |
| for (var i:int = 0; i < _instances.length; i++) |
| { |
| if (_instances[i]) |
| return IEffectInstance(_instances[i]).playheadTime; |
| } |
| // Effect isn't running: return the cached value |
| return _playheadTime; |
| } |
| public function set playheadTime(value:Number):void |
| { |
| // If the effect is not yet playing, it should still be possible |
| // to seek into it. playing and then pausing it provides that |
| // capability |
| // TODO (chaase): Need better overall mechanism to seek into a |
| // non-playing effect. The internals of seeking in Animation |
| // are complicated and don't end up giving us the behavior we |
| // want, especially for successive seeks. |
| var started:Boolean = false; |
| if (_instances.length == 0) |
| { |
| play(); |
| started = true; |
| } |
| for (var i:int = 0; i < _instances.length; i++) |
| { |
| if (_instances[i]) |
| EffectInstance(_instances[i]).playheadTime = value; |
| } |
| if (started) |
| pause(); |
| _playheadTime = value; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| |
| |
| /** |
| * @copy mx.effects.IEffect#getAffectedProperties() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getAffectedProperties():Array /* of String */ |
| { |
| // Every subclass should override this method. |
| return []; |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#createInstances() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function createInstances(targets:Array = null):Array /* of EffectInstance */ |
| { |
| if (!targets) |
| targets = this.targets; |
| |
| var newInstances:Array = []; |
| |
| // Multiple target support |
| var n:int = targets.length; |
| var offsetDelay:Number = 0; |
| |
| for (var i:int = 0; i < n; i++) |
| { |
| var newInstance:IEffectInstance = createInstance(targets[i]); |
| |
| if (newInstance) |
| { |
| newInstance.startDelay += offsetDelay; |
| offsetDelay += perElementOffset; |
| newInstances.push(newInstance); |
| } |
| } |
| |
| triggerEvent = null; |
| |
| return newInstances; |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#createInstance() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function createInstance(target:Object = null):IEffectInstance |
| { |
| if (!target) |
| target = this.target; |
| |
| var newInstance:IEffectInstance = null; |
| var props:PropertyChanges = null; |
| var create:Boolean = true; |
| var setPropsArray:Boolean = false; |
| |
| if (propertyChangesArray) |
| { |
| setPropsArray = true; |
| create = filterInstance(propertyChangesArray, |
| target); |
| } |
| |
| if (create) |
| { |
| newInstance = IEffectInstance(new instanceClass(target)); |
| |
| initInstance(newInstance); |
| |
| if (setPropsArray) |
| { |
| var n:int = propertyChangesArray.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| if (propertyChangesArray[i].target == target) |
| { |
| newInstance.propertyChanges = |
| propertyChangesArray[i]; |
| } |
| } |
| } |
| |
| EventDispatcher(newInstance).addEventListener(EffectEvent.EFFECT_START, effectStartHandler); |
| EventDispatcher(newInstance).addEventListener(EffectEvent.EFFECT_STOP, effectStopHandler); |
| EventDispatcher(newInstance).addEventListener(EffectEvent.EFFECT_END, effectEndHandler); |
| |
| _instances.push(newInstance); |
| |
| if (triggerEvent) |
| newInstance.initEffect(triggerEvent); |
| } |
| |
| return newInstance; |
| } |
| |
| /** |
| * Copies properties of the effect to the effect instance. |
| * |
| * <p>Flex calls this method from the <code>Effect.createInstance()</code> |
| * method; you do not have to call it yourself. </p> |
| * |
| * <p>When you create a custom effect, override this method to |
| * copy properties from the Effect class to the effect instance class. |
| * In your override, call <code>super.initInstance()</code>. </p> |
| * |
| * @param EffectInstance The effect instance to initialize. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function initInstance(instance:IEffectInstance):void |
| { |
| instance.duration = duration; |
| Object(instance).durationExplicitlySet = durationExplicitlySet; |
| instance.effect = this; |
| instance.effectTargetHost = effectTargetHost; |
| instance.hideFocusRing = hideFocusRing; |
| instance.repeatCount = repeatCount; |
| instance.repeatDelay = repeatDelay; |
| instance.startDelay = startDelay; |
| instance.suspendBackgroundProcessing = suspendBackgroundProcessing; |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#deleteInstance() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function deleteInstance(instance:IEffectInstance):void |
| { |
| EventDispatcher(instance).removeEventListener( |
| EffectEvent.EFFECT_START, effectStartHandler); |
| EventDispatcher(instance).removeEventListener( |
| EffectEvent.EFFECT_STOP, effectStopHandler); |
| EventDispatcher(instance).removeEventListener( |
| EffectEvent.EFFECT_END, effectEndHandler); |
| |
| var n:int = _instances.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| if (_instances[i] === instance) |
| _instances.splice(i, 1); |
| } |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#play() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function play(targets:Array = null, |
| playReversedFromEnd:Boolean = false): |
| Array /* of EffectInstance */ |
| { |
| effectStopped = false; |
| isPaused = false; |
| playReversed = playReversedFromEnd; |
| |
| // If we have a propertyChangesArray, capture the current values |
| // if they haven't been captured already, strip out any unchanged |
| // values, then apply the start values. |
| if (targets == null && propertyChangesArray != null) |
| { |
| if (_callValidateNow) |
| LayoutManager.getInstance().validateNow(); |
| |
| if (!endValuesCaptured) |
| propertyChangesArray = |
| captureValues(propertyChangesArray, false); |
| |
| propertyChangesArray = |
| stripUnchangedValues(propertyChangesArray); |
| |
| applyStartValues(propertyChangesArray, |
| this.targets); |
| |
| if (playReversedFromEnd) |
| { |
| for (var j:int = 0; j < propertyChangesArray.length; ++j) |
| { |
| var tmpStart:Object = propertyChangesArray[j].start; |
| propertyChangesArray[j].start = propertyChangesArray[j].end; |
| propertyChangesArray[j].end = tmpStart; |
| } |
| } |
| // Revalidate after applying the start values, to get everything |
| // back the way it should be before starting the animation |
| LayoutManager.getInstance().validateNow(); |
| |
| applyEndValuesWhenDone = true; |
| } |
| |
| var newInstances:Array = createInstances(targets); |
| |
| var n:int = newInstances.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| var newInstance:IEffectInstance = IEffectInstance(newInstances[i]); |
| |
| Object(newInstance).playReversed = playReversedFromEnd; |
| |
| newInstance.startEffect(); |
| } |
| |
| return newInstances; |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#pause() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function pause():void |
| { |
| if (isPlaying && !isPaused) |
| { |
| isPaused = true; |
| |
| var n:int = _instances.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| IEffectInstance(_instances[i]).pause(); |
| } |
| } |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#stop() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function stop():void |
| { |
| var n:int = _instances.length - 1; |
| for (var i:int = n; i >= 0; i--) |
| { |
| var instance:IEffectInstance = IEffectInstance(_instances[i]); |
| if (instance) |
| instance.stop(); |
| } |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#resume() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function resume():void |
| { |
| if (isPlaying && isPaused) |
| { |
| isPaused = false; |
| var n:int = _instances.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| IEffectInstance(_instances[i]).resume(); |
| } |
| } |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#reverse() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function reverse():void |
| { |
| if (isPlaying) |
| { |
| var n:int = _instances.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| IEffectInstance(_instances[i]).reverse(); |
| } |
| } |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#end() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function end(effectInstance:IEffectInstance = null):void |
| { |
| if (effectInstance) |
| { |
| effectInstance.end(); |
| } |
| else |
| { |
| var n:int = _instances.length; |
| for (var i:int = n - 1; i >= 0; i--) |
| { |
| var instance:IEffectInstance = IEffectInstance(_instances[i]); |
| if (instance) |
| instance.end(); |
| } |
| } |
| } |
| |
| /** |
| * Determines the logic for filtering out an effect instance. |
| * The CompositeEffect class overrides this method. |
| * |
| * @param propChanges The properties modified by the effect. |
| * |
| * @param targ The effect target. |
| * |
| * @return Returns <code>true</code> if the effect instance should play. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function filterInstance(propChanges:Array, target:Object):Boolean |
| { |
| if (filterObject) |
| return filterObject.filterInstance(propChanges, effectTargetHost, target); |
| |
| return true; |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#captureStartValues() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function captureStartValues():void |
| { |
| if (targets.length > 0) |
| { |
| // Reset the PropertyChanges array by passing in 'null' |
| propertyChangesArray = captureValues(null, true); |
| |
| _callValidateNow = true; |
| } |
| endValuesCaptured = false; |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#captureMoreStartValues() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function captureMoreStartValues(targets:Array):void |
| { |
| if (targets.length > 0) |
| { |
| // make temporary PropertyChangesArray |
| var additionalPropertyChangesArray:Array = captureValues(null, true); |
| |
| propertyChangesArray = (propertyChangesArray != null) ? |
| propertyChangesArray.concat(additionalPropertyChangesArray) : |
| additionalPropertyChangesArray; |
| } |
| } |
| |
| /** |
| * @copy mx.effects.IEffect#captureEndValues() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function captureEndValues():void |
| { |
| // captureValues will create propertyChangesArray if it does not |
| // yet exist |
| propertyChangesArray = |
| captureValues(propertyChangesArray, false); |
| endValuesCaptured = true; |
| } |
| |
| /** |
| * @private |
| * Used internally to grab the values of the relevant properties |
| */ |
| mx_internal function captureValues(propChanges:Array, |
| setStartValues:Boolean, |
| targetsToCapture:Array = null):Array |
| { |
| var n:int; |
| var i:int; |
| if (!propChanges) |
| { |
| propChanges = []; |
| |
| // Create a new PropertyChanges object for the sum of all targets. |
| n = targets.length; |
| for (i = 0; i < n; i++) |
| propChanges.push(new PropertyChanges(targets[i])); |
| } |
| |
| // Merge Effect.filterProperties and filterObject.filterProperties |
| var effectProps:Array = !filterObject ? |
| relevantProperties : |
| mergeArrays(relevantProperties, |
| filterObject.filterProperties); |
| |
| var valueMap:Object; |
| var target:Object; |
| var m:int; |
| var j:int; |
| |
| // For each target, grab the property's value |
| // and put it into the propChanges Array. |
| // Walk the targets. |
| if (effectProps && effectProps.length > 0) |
| { |
| n = propChanges.length; |
| for (i = 0; i < n; i++) |
| { |
| target = propChanges[i].target; |
| if (targetsToCapture == null || targetsToCapture.length == 0 || |
| targetsToCapture.indexOf(target) >= 0) |
| { |
| valueMap = setStartValues ? propChanges[i].start : propChanges[i].end; |
| |
| // Walk the properties in the target |
| m = effectProps.length; |
| for (j = 0; j < m; j++) |
| { |
| // Don't clobber values already set |
| if (valueMap[effectProps[j]] === undefined) |
| { |
| valueMap[effectProps[j]] = |
| getValueFromTarget(target,effectProps[j]); |
| } |
| } |
| } |
| } |
| } |
| |
| var styles:Array = !filterObject ? |
| relevantStyles : |
| mergeArrays(relevantStyles, |
| filterObject.filterStyles); |
| |
| if (styles && styles.length > 0) |
| { |
| n = propChanges.length; |
| for (i = 0; i < n; i++) |
| { |
| target = propChanges[i].target; |
| if (targetsToCapture == null || targetsToCapture.length == 0 || |
| targetsToCapture.indexOf(target) >= 0) |
| { |
| if (!(target is IStyleClient)) |
| continue; |
| |
| valueMap = setStartValues ? propChanges[i].start : propChanges[i].end; |
| |
| // Walk the properties in the target. |
| m = styles.length; |
| for (j = 0; j < m; j++) |
| { |
| // Don't clobber values set by relevantProperties |
| if (valueMap[styles[j]] === undefined) |
| { |
| var value:* = target.getStyle(styles[j]); |
| valueMap[styles[j]] = value; |
| } |
| } |
| } |
| } |
| } |
| |
| return propChanges; |
| } |
| |
| /** |
| * Called by the <code>captureStartValues()</code> method to get the value |
| * of a property from the target. |
| * This function should only be called internally |
| * by the effects framework. |
| * The default behavior is to simply return <code>target[property]</code>. |
| * Effect developers can override this function |
| * if you need a different behavior. |
| * |
| * @param target The effect target. |
| * |
| * @param property The target property. |
| * |
| * @return The value of the target property. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function getValueFromTarget(target:Object, property:String):* |
| { |
| if (property in target) |
| return target[property]; |
| |
| return undefined; |
| } |
| |
| /** |
| * @private |
| * Applies the start values found in the array of PropertyChanges |
| * to the relevant targets. |
| */ |
| mx_internal function applyStartValues(propChanges:Array, |
| targets:Array):void |
| { |
| var effectProps:Array = relevantProperties; |
| |
| var n:int = propChanges.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| var m:int; |
| var j:int; |
| |
| var target:Object = propChanges[i].target; |
| var apply:Boolean = false; |
| |
| m = targets.length; |
| for (j = 0; j < m; j++) |
| { |
| if (targets[j] == target) |
| { |
| apply = filterInstance(propChanges, target); |
| break; |
| } |
| } |
| |
| if (apply) |
| { |
| // Walk the properties in the target |
| m = effectProps.length; |
| for (j = 0; j < m; j++) |
| { |
| var propName:String = effectProps[j]; |
| var startVal:* = propChanges[i].start[propName]; |
| var endVal:* = propChanges[i].end[propName]; |
| if (propName in propChanges[i].start && |
| endVal != startVal && |
| (!(startVal is Number) || |
| !(isNaN(endVal) && isNaN(startVal)))) |
| { |
| applyValueToTarget(target, effectProps[j], |
| propChanges[i].start[effectProps[j]], |
| propChanges[i].start); |
| } |
| } |
| |
| // Walk the styles in the target |
| m = relevantStyles.length; |
| for (j = 0; j < m; j++) |
| { |
| var styleName:String = relevantStyles[j]; |
| var startStyle:* = propChanges[i].start[styleName]; |
| var endStyle:* = propChanges[i].end[styleName]; |
| if (styleName in propChanges[i].start && |
| endStyle != startStyle && |
| (!(startStyle is Number) || |
| !(isNaN(endStyle) && isNaN(startStyle))) && |
| target is IStyleClient) |
| { |
| if (propChanges[i].end[relevantStyles[j]] !== undefined) |
| target.setStyle(relevantStyles[j], propChanges[i].start[relevantStyles[j]]); |
| else |
| target.clearStyle(relevantStyles[j]); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * @private |
| * Applies the start values found in the array of PropertyChanges |
| * to the relevant targets. |
| */ |
| mx_internal function applyEndValues(propChanges:Array, |
| targets:Array):void |
| { |
| // For now, only new Flex4 effects will apply end values when transitions |
| // are over, to preserve the previous behavior of Flex3 effects |
| if (!applyTransitionEndProperties) |
| return; |
| |
| var effectProps:Array = relevantProperties; |
| |
| var n:int = propChanges.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| var m:int; |
| var j:int; |
| |
| var target:Object = propChanges[i].target; |
| var apply:Boolean = false; |
| |
| m = targets.length; |
| for (j = 0; j < m; j++) |
| { |
| if (targets[j] == target) |
| { |
| apply = filterInstance(propChanges, target); |
| break; |
| } |
| } |
| |
| if (apply) |
| { |
| // Walk the properties in the target |
| m = effectProps.length; |
| for (j = 0; j < m; j++) |
| { |
| var propName:String = effectProps[j]; |
| var startVal:* = propChanges[i].start[propName]; |
| var endVal:* = propChanges[i].end[propName]; |
| if (propName in propChanges[i].end && |
| (!(endVal is Number) || |
| !(isNaN(endVal) && isNaN(startVal)))) |
| { |
| applyValueToTarget(target, propName, |
| propChanges[i].end[propName], |
| propChanges[i].end); |
| } |
| } |
| |
| // Walk the styles in the target |
| m = relevantStyles.length; |
| for (j = 0; j < m; j++) |
| { |
| var styleName:String = relevantStyles[j]; |
| var startStyle:* = propChanges[i].start[styleName]; |
| var endStyle:* = propChanges[i].end[styleName]; |
| if (styleName in propChanges[i].end && |
| (!(endStyle is Number) || |
| !(isNaN(endStyle) && isNaN(startStyle))) && |
| target is IStyleClient) |
| { |
| if (propChanges[i].end[styleName] !== undefined) |
| target.setStyle(styleName, propChanges[i].end[styleName]); |
| else |
| target.clearStyle(styleName); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Used internally by the Effect infrastructure. |
| * If <code>captureStartValues()</code> has been called, |
| * then when Flex calls the <code>play()</code> method, it uses this function |
| * to set the targets back to the starting state. |
| * The default behavior is to take the value captured |
| * using the <code>getValueFromTarget()</code> method |
| * and set it directly on the target's property. For example: <pre> |
| * |
| * target[property] = value;</pre> |
| * |
| * <p>Only override this method if you need to apply |
| * the captured values in a different way. |
| * Note that style properties of a target are set |
| * using a different mechanism. |
| * Use the <code>relevantStyles</code> property to specify |
| * which style properties to capture and apply. </p> |
| * |
| * @param target The effect target. |
| * |
| * @param property The target property. |
| * |
| * @param value The value of the property. |
| * |
| * @param props Array of Objects, where each Array element contains a |
| * <code>start</code> and <code>end</code> Object |
| * for the properties that the effect is monitoring. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function applyValueToTarget(target:Object, property:String, |
| value:*, props:Object):void |
| { |
| if (property in target) |
| { |
| // The "property in target" test only tells if the property exists |
| // in the target, but does not distinguish between read-only and |
| // read-write properties. Put a try/catch around the setter and |
| // ignore any errors. |
| try |
| { |
| |
| if (applyActualDimensions && |
| target is IFlexDisplayObject && |
| property == "height") |
| { |
| target.setActualSize(target.width,value); |
| } |
| else if (applyActualDimensions && |
| target is IFlexDisplayObject && |
| property == "width") |
| { |
| target.setActualSize(value,target.height); |
| } |
| else |
| { |
| target[property] = value; |
| } |
| } |
| catch(e:Error) |
| { |
| // Ignore errors |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * This method is called when the effect instance starts playing. |
| * If you override this method, ensure that you call the super method. |
| * |
| * @param event An event object of type EffectEvent. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function effectStartHandler(event:EffectEvent):void |
| { |
| dispatchEvent(event); |
| } |
| |
| /** |
| * Called when an effect instance has stopped by a call |
| * to the <code>stop()</code> method. |
| * If you override this method, ensure that you call the super method. |
| * |
| * @param event An event object of type EffectEvent. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function effectStopHandler(event:EffectEvent):void |
| { |
| dispatchEvent(event); |
| // We use this event to determine whether we should set final |
| // state values in the ensuing endHandler() call |
| effectStopped = true; |
| } |
| |
| /** |
| * Called when an effect instance has finished playing. |
| * If you override this method, ensure that you call the super method. |
| * |
| * @param event An event object of type EffectEvent. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function effectEndHandler(event:EffectEvent):void |
| { |
| if (playReversed && propertyChangesArray != null) |
| { |
| for (var j:int = 0; j < propertyChangesArray.length; ++j) |
| { |
| var tmpStart:Object = propertyChangesArray[j].start; |
| propertyChangesArray[j].start = propertyChangesArray[j].end; |
| propertyChangesArray[j].end = tmpStart; |
| } |
| } |
| var lastTime:Boolean = !_instances || _instances.length == 1; |
| |
| // Transitions should set the end values when done |
| if (applyEndValuesWhenDone && !effectStopped && lastTime) |
| applyEndValues(propertyChangesArray, targets); |
| |
| var instance:IEffectInstance = IEffectInstance(event.effectInstance); |
| |
| deleteInstance(instance); |
| |
| dispatchEvent(event); |
| |
| if (lastTime) |
| { |
| propertyChangesArray = null; |
| applyEndValuesWhenDone = false; |
| } |
| } |
| |
| } |
| |
| } |