////////////////////////////////////////////////////////////////////////////////
//
// 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 end()
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 stop()
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.
*
*
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.
* * @mxml * *The Effect class defines the following properties, * which all of its subclasses inherit:
* ** <mx:tagname * Properties * customFilter="" * duration="500" * filter="" * hideFocusRing="false" * perElementOffset="0" * repeatCount="1" * repeatDelay="0" * startDelay="0" * suspendBackgroundProcessing="false|true" * target="effect target" * targets="array of effect targets" * * Events * effectEnd="No default" * efectStart="No default" * /> ** * @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. * *
Starting an effect is usually a three-step process:
* *new
operator.duration
.play()
method
* or assign the effect to a trigger.true
if the end values
* of an effect have already been determined,
* or false
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.
*
* All subclasses of the Effect class must set this property * in their constructor.
* * @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 theend()
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 repeatCount
* property, the startDelay
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 true
, 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 false
.
*
* You are encouraged to set this property to
* true
in most cases, because it improves
* the performance of the application.
* However, the property should be set to false
* if either of the following is true:
startDelay
,
* repeatCount
, and repeatDelay
.
*
* @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.
*
* Flex calls this method from the Effect.createInstance()
* method; you do not have to call it yourself.
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 super.initInstance()
.
true
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 captureStartValues()
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 target[property]
.
* 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 captureStartValues()
has been called,
* then when Flex calls the play()
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 getValueFromTarget()
method
* and set it directly on the target's property. For example: * * target[property] = value;* *
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 relevantStyles
property to specify
* which style properties to capture and apply.
start
and end
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 stop()
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;
}
}
}
}