[Laszlo-checkins] r11453 - openlaszlo/trunk/WEB-INF/lps/lfc/controllers

bargull@openlaszlo.org bargull at openlaszlo.org
Wed Oct 15 01:37:52 PDT 2008


Author: bargull
Date: 2008-10-15 01:37:48 -0700 (Wed, 15 Oct 2008)
New Revision: 11453

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LaszloAnimation.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LzAnimatorGroup.lzs
Log:
Change 20081014-bargull-PUY by bargull at dell--p4--2-53 on 2008-10-14 23:26:36
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: animator fixes

New Features:

Bugs Fixed: LPP-6338, LPP-7153, LPP-7158

Technical Reviewer: pbr
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
LzAnimatorGroup:
- marked constructor and internal properties as doc-private
- added setter for "repeat" (LPP-7153)
- adjusted doc-types (repeat, started, process)
- added typing
- removed long-time deprecated event "onfinish" (already deprecated in LPS3.1)
- updated "checkRepeat()"-method (LPP-7153)
- check "immediateparent"-animators in "destroy()" (to be compatible to "construct()")
- changed casts to use "cast"-operator in "destroy()" (LPP-7158)

LzAnimator:
- marked constructor and internal properties as doc-private
- added typing

(And did some work for the all-time favourite LPP-2623.)
    

Tests:
run animation example in swf8-9/dhtml
testcase from LPP-7153
testcase from LPP-7158



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LaszloAnimation.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LaszloAnimation.lzs	2008-10-15 08:00:11 UTC (rev 11452)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LaszloAnimation.lzs	2008-10-15 08:37:48 UTC (rev 11453)
@@ -1,5 +1,5 @@
 /**
-  * LaszloAnimations.as 
+  * LaszloAnimations.as
   *
   * @copyright Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.
   *            Use is subject to license terms.
@@ -14,7 +14,7 @@
   * specified duration in milliseconds. For example, the following program
   * defines an animator for a window that moves it to a position of x=100
   * over 1 second (1000 milliseconds).</p>
-  * 
+  *
   * <example><programlisting class="code" extract="false">
   * &lt;canvas>
   *   &lt;window>
@@ -22,7 +22,7 @@
   *   &lt;/window>
   * &lt;/canvas>
   * </programlisting></example>
-  * 
+  *
   * <p>See the <a href="${dguide}animation.html">Guide</a> for a complete discussion of
   * animators and animation in Laszlo applications.</p>
   *
@@ -30,398 +30,397 @@
   * @shortdesc Changes the value of another object's attribute over time.
   * @see animatorgroup
   */
-dynamic class LzAnimator extends LzAnimatorGroup {
+public dynamic class LzAnimator extends LzAnimatorGroup {
 
-  function LzAnimator ( parent:* , attrs:* , children:* = null, instcall:*  = null) {
-      this.calcMethod = this.calcNextValue;
-      super(parent,attrs,children,instcall);
-   }
+    /** @access private */
+    public function LzAnimator (parent:LzNode? = null, attrs:Object? = null, children:Array? = null, instcall:Boolean = false) {
+        super(parent, attrs, children, instcall);
+    }
 
+    /** @access private
+      * @modifiers override
+      */
+    static var tagname :String = 'animator';
+    /** @access private */
+    static var attributes :Object = new LzInheritedHash(LzAnimatorGroup.attributes);
 
-/** @access private
-  * @modifiers override 
-  */
-static var tagname = 'animator';
-/** @access private */
-static var attributes = new LzInheritedHash(LzAnimatorGroup.attributes);
+    /** @access private */
+    var calcMethod:Function;
+    /** @access private */
+    var lastIterationTime:Number;
+    /** @access private */
+    var currentValue:Number;
+    /** @access private */
+    var doBegin:Boolean;
+    /** @access private */
+    var beginPoleDelta:Number = .25;
+    /** @access private */
+    var endPoleDelta:Number = .25;
+    /** @access private */
+    var primary_K:Number;
+    /** @access private */
+    var origto:Number;
 
-var calcMethod:Function;
+    /**
+      * @access private
+      */
+    override function construct (parent, args) {
+        super.construct(parent, args);
+        this.calcMethod = this.calcNextValue;
+        this.primary_K = 1.0;
+    }
 
-var lastIterationTime:Number;
-var currentValue:Number;
-var doBegin:Boolean;
+    /**
+      * Sets the motion style for the animator.
+      * @param String eparam: One of "easein", "easeout" , "linear" or "easeboth"
+      * to describe how the animator accelerates and decelerates. The default is
+      * "easeboth".
+      * @access private
+      */
+    function $lzc$set_motion (eparam) {
+        this.motion = eparam;
+        //easin, easeout , linear , easeboth (default)
+        if (eparam == "linear") {
+            this.calcMethod = this.calcNextValueLinear;
+        } else {
+            this.calcMethod = this.calcNextValue;
+            if (eparam == "easeout") {
+                this.beginPoleDelta = 100;
+            } else if (eparam == "easein") {
+                this.endPoleDelta = 15;
+            }
+        }
+    }
 
-var beginPoleDelta:Number = .25;
-var endPoleDelta:Number = .25;
-
-var primary_K:Number;
-var origto:Number;
-
-/**
-  * @access private
-  */
-override function construct ( parent , args ){
-    super.construct.apply(this, arguments);
-    this.primary_K          = 1.0;
-}
-
-/**
-  * Sets the motion style for the animator.
-  * @param String eparam: One of "easein", "easeout" , "linear" or "easeboth"
-  * to describe how the animator accelerates and decelerates. The default is
-  * "easeboth".
-  * @access private
-  */
-function $lzc$set_motion ( eparam ){
-    this.motion = eparam
-    //easin, easeout , linear , easeboth (default)
-    if ( eparam == "linear" ){
-        this.calcMethod = this.calcNextValueLinear;
-    } else {
-        this.calcMethod =  this.calcNextValue;
-        if ( eparam == "easeout" ){
-            this.beginPoleDelta = 100;
-        } else if ( eparam == "easein" ){
-            this.endPoleDelta = 15;
+    /**
+     * @deprecated in 4.1
+     * @deprecated Use setAttribute('motion', ...) instead.
+     * @access private
+     */
+    final function setMotion (eparam) {
+        if ($debug) {
+            Debug.deprecated(this, arguments.callee, this.setAttribute);
         }
+        this.$lzc$set_motion(eparam);
     }
-}
-/**
- * @deprecated in 4.1
- * @deprecated Use setAttribute('motion', ...) instead.
- * @access private
- */
-final function setMotion (eparam) {
-  if ($debug) {
-    Debug.deprecated(this, arguments.callee, this.setAttribute);
-  }
-  this.$lzc$set_motion(eparam);
-}
 
+    /**
+      * Sets the destination value for the animator
+      * @param Number eparam: The destination value for the animator.
+      * @access private
+      */
+    function $lzc$set_to (eparam) {
+        this.origto = Number(eparam);
+    }
 
-/**
-  * Sets the destination value for the animator
-  * @param Number eparam: The destination value for the animator.
-  * @access private
-  */
-function $lzc$set_to ( eparam ) {
-    this.origto = Number(eparam);
-}
-/**
- * @deprecated in 4.1
- * @deprecated Use setAttribute('to', ...) instead.
- * @access private
- */
-final function setTo (eparam) {
-  if ($debug) {
-    Debug.deprecated(this, arguments.callee, this.setAttribute);
-  }
-  this.$lzc$set_to(eparam);
-}
-
-
-/**
-  * Calculate the control values  fro the animation. These will not change even
-  * if the animation is repeated.
-  *
-  * @access private
-  */
-function calcControlValues ( cval  = null){
-    // reset currentValue
-    this.currentValue = cval || 0;
-
-    // create direction multiplier
-    var dir = this.indirect ? -1 : 1;
-
-    // set beginPole and endPole values
-    if ( this.currentValue < this.to ) {
-        this.beginPole = this.currentValue - dir*this.beginPoleDelta;
-        this.endPole = this.to + dir*this.endPoleDelta;
-    }else{
-        this.beginPole = this.currentValue + dir*this.beginPoleDelta;
-        this.endPole = this.to - dir*this.endPoleDelta;
+    /**
+     * @deprecated in 4.1
+     * @deprecated Use setAttribute('to', ...) instead.
+     * @access private
+     */
+    final function setTo (eparam) {
+        if ($debug) {
+            Debug.deprecated(this, arguments.callee, this.setAttribute);
+        }
+        this.$lzc$set_to(eparam);
     }
 
-    // calculate value for primary_K
-    // a default value of 1.0 means the attribute will be static, i.e.
-    // the animation will still be calculated but the result will
-    // always be the same.
-    this.primary_K = 1.0;
+    /**
+      * Calculate the control values for the animation. These will not change even
+      * if the animation is repeated.
+      *
+      * @access private
+      */
+    function calcControlValues (cval = null) :void {
+        // reset currentValue
+        this.currentValue = cval || 0;
 
-    var kN = 1.0*(this.beginPole - this.to )*
-                 (this.currentValue - this.endPole);
+        // create direction multiplier
+        var dir:int = this.indirect ? -1 : 1;
 
-    var kD = 1.0*(this.beginPole - this.currentValue)*
-                 (this.to - this.endPole);
+        // set beginPole and endPole values
+        if (this.currentValue < this.to) {
+            this.beginPole = this.currentValue - dir * this.beginPoleDelta;
+            this.endPole = this.to + dir * this.endPoleDelta;
+        } else {
+            this.beginPole = this.currentValue + dir * this.beginPoleDelta;
+            this.endPole = this.to - dir * this.endPoleDelta;
+        }
 
-    // NOTE: in future this should probaly check for really small amounts not
-    // just zero
-    if (kD != 0) this.primary_K = Math.abs(kN/kD);
+        // calculate value for primary_K
+        // a default value of 1.0 means the attribute will be static, i.e.
+        // the animation will still be calculated but the result will
+        // always be the same.
+        this.primary_K = 1.0;
 
-}
+        var kN:Number = 1.0 * (this.beginPole - this.to) *
+                              (this.currentValue - this.endPole);
 
+        var kD:Number = 1.0 * (this.beginPole - this.currentValue) *
+                              (this.to - this.endPole);
 
-/**
-  * this is called once to set any starting values that will only need to be
-  * calculated once even if the animator repeats
-  *
-  * BRET'S NOTE:  this.target.setAttribute( this.attribute , this.from ); not true if relative
-  * if doStart is called while animator is active, just return
-  * else if a "from" value has been specified then this
-  * Here is where the expected value for a view should be updated
-  *
-  * @access private
-  */
-override function doStart (){
-    if ( this.isactive ) return;
-    this.isactive = true;
+        // NOTE: in future this should probaly check for really small amounts not
+        // just zero
+        if (kD != 0) this.primary_K = Math.abs(kN / kD);
+    }
 
-    this.prepareStart();
+    /**
+      * this is called once to set any starting values that will only need to be
+      * calculated once even if the animator repeats
+      *
+      * BRET'S NOTE:  this.target.setAttribute( this.attribute, this.from ); not true if relative
+      * if doStart is called while animator is active, just return
+      * else if a "from" value has been specified then this
+      * Here is where the expected value for a view should be updated
+      *
+      * @access private
+      */
+    override function doStart () {
+        if (this.isactive) return;
+        this.isactive = true;
 
-    // give this animator processing time by registering it with lz.Idle service
-    this.updateDel.register( lz.Idle , "onidle" );
-}
+        this.prepareStart();
 
-
-/**
-  * @access private
-  */
-override function prepareStart ( ){
-    // create a "repeat" counter to be decremented each time after the
-    // animator finishes a cycle.
-    this.crepeat = this.repeat;
-
-
-    // Set the attribute of the view to its "from" value but make sure
-    // expectedAttribute is updated.
-    if ( this.from != null ){
-        this.target.setAttribute( this.attribute , Number( this.from ) );
+        // give this animator processing time by registering it with lz.Idle service
+        this.updateDel.register(lz.Idle, "onidle");
     }
 
-    if ( this.relative ) {
-        this.to = this.origto;
-    }else{
-        this.to = this.origto - this.target.getExpectedAttribute(this.attribute);
+    /**
+      * @access private
+      */
+    override function prepareStart () :void {
+        // create a "repeat" counter to be decremented each time after the
+        // animator finishes a cycle.
+        this.crepeat = this.repeat;
+        var targ:LzNode = this.target;
+        var attr:String = this.attribute;
 
-        // "to" has changed so calc new poles and K value
-        //this.calcControlValues();
-    }
+        // Set the attribute of the view to its "from" value but make sure
+        // expectedAttribute is updated.
+        if (this.from != null) {
+            targ.setAttribute(attr, Number(this.from));
+        }
 
-    // update the expected attribute for this view so that animators attached
-    // after this one will can execute appropriately.
-    this.target.addToExpectedAttribute( this.attribute,this.to );
+        if (this.relative) {
+            this.to = this.origto;
+        } else {
+            this.to = this.origto - targ.getExpectedAttribute(attr);
 
-    // everytime an animator is started, a counter associated with that property
-    // is incremented. When this counter is decremented and reaches zero then
-    // the final expected value will be assigned to that attribute
-    this.target.__LZincrementCounter(this.attribute);
+            // "to" has changed so calc new poles and K value
+            //this.calcControlValues();
+        }
 
+        // update the expected attribute for this view so that animators attached
+        // after this one will can execute appropriately.
+        targ.addToExpectedAttribute(attr, this.to);
 
-    // set current to zero since all animators are now relative
-    this.currentValue = 0;
+        // everytime an animator is started, a counter associated with that property
+        // is incremented. When this counter is decremented and reaches zero then
+        // the final expected value will be assigned to that attribute
+        targ.__LZincrementCounter(attr);
 
-    //we already did this if !this.relative -- conditionalize?
-    this.calcControlValues();
+        // set current to zero since all animators are now relative
+        this.currentValue = 0;
 
-    this.doBegin = true;
+        //we already did this if !this.relative -- conditionalize?
+        this.calcControlValues();
 
-}
-
-/**
-  * reset the time variables and currentValue
-  * @access private
-  */
-override function resetAnimator() {
-    // Set the attribute of the view to its "from" value but make sure
-    // expectedAttribute is updated.
-    if ( this.from != null ){
-        this.target.setAttribute( this.attribute , this.from );
-        var d = this.from - this.target.getExpectedAttribute( this.attribute );
-        this.target.addToExpectedAttribute(this.attribute,d);
+        this.doBegin = true;
     }
 
-    if (!this.relative) {
-        this.to = this.origto - this.target.getExpectedAttribute( this.attribute );
-        // "to" has changed so calc new poles and K value
-        this.calcControlValues();
-    }
+    /**
+      * reset the time variables and currentValue
+      * @access private
+      */
+    override function resetAnimator () :void {
+        // Set the attribute of the view to its "from" value but make sure
+        // expectedAttribute is updated.
+        var targ:LzNode = this.target;
+        var attr:String = this.attribute;
 
-    // update the expected attribute for this view so that animators attached
-    // after this one will can execute appropriately.
-    this.target.addToExpectedAttribute(this.attribute,this.to);
-    this.target.__LZincrementCounter(this.attribute);
+        var from:* = this.from;
+        if (from != null) {
+            targ.setAttribute(attr, from);
+            var d:Number = from - targ.getExpectedAttribute(attr);
+            targ.addToExpectedAttribute(attr, d);
+        }
 
-    // set current to zero since all animators are now relative
-    this.currentValue = 0;
+        if (! this.relative) {
+            this.to = this.origto - targ.getExpectedAttribute(attr);
+            // "to" has changed so calc new poles and K value
+            this.calcControlValues();
+        }
 
-    this.doBegin = true;
-}
+        // update the expected attribute for this view so that animators attached
+        // after this one will can execute appropriately.
+        targ.addToExpectedAttribute(attr, this.to);
+        targ.__LZincrementCounter(attr);
 
+        // set current to zero since all animators are now relative
+        this.currentValue = 0;
 
-/**
-  * beginAnimator is called on the first iteration of the animator.
-  *
-  * @access private
-  *
-  * @param Number time: the time in milliseconds that this animator will
-  * be assigned as its beginning time.
-  */
-function beginAnimator( time ) {
+        this.doBegin = true;
+    }
 
-    // set initial time parameters
-    this.startTime = time;
-    this.lastIterationTime = time;
+    /**
+      * beginAnimator is called on the first iteration of the animator.
+      *
+      * @access private
+      *
+      * @param Number time: the time in milliseconds that this animator will
+      * be assigned as its beginning time.
+      */
+    function beginAnimator (time:Number) :void {
+        // set initial time parameters
+        this.startTime = time;
+        this.lastIterationTime = time;
 
-    if (this.onstart.ready) this.onstart.sendEvent( time );
+        if (this.onstart.ready) this.onstart.sendEvent(time);
 
-    //Set to false so next update does not call this function
-    this.doBegin = false;
+        //Set to false so next update does not call this function
+        this.doBegin = false;
+    }
 
+    /**
+      * @access private
+      */
+    override function stop () {
+        if (! this.isactive) return;
 
-}
+        var targ:LzNode = this.target;
+        var e_prop:String = "e_" + this.attribute;
+        if (! targ[e_prop].c) {
+            targ[e_prop].c = 0;
+        }
+        targ[e_prop].c -= 1; //decrement animation counter for prop
+        if (targ[e_prop].c <= 0) {
+            targ[e_prop].c = 0;
+            targ[e_prop].v = null;
+        } else {
+            targ[e_prop].v -= this.to - this.currentValue;
+        }
 
-/**
-  * @access private
-  */
-override function stop( ) {
-    if ( !this.isactive ) return;
-
-    var e_prop = "e_" +  this.attribute;
-    if (!this.target[e_prop].c) { this.target[e_prop].c = 0; }
-    this.target[e_prop].c--; //decrement animation counter for prop
-    if ( this.target[e_prop].c <= 0 ){
-        this.target[e_prop].c = 0;
-        this.target[e_prop].v = null;
-    } else {
-        this.target[e_prop].v -= this.to - this.currentValue;
+        this.__LZhalt();
     }
 
-    this.__LZhalt();
-}
+    /**
+      * @access private
+      */
+    override function __LZfinalizeAnim () :void {
+        var targ:LzNode = this.target;
+        var e_prop:String = "e_" + this.attribute;
+        if (! targ[e_prop].c) {
+            targ[e_prop].c = 0;
+        }
+        targ[e_prop].c -= 1; //decrement animation counter for prop
+        if (targ[e_prop].c <= 0) {
+            targ[e_prop].c = 0;
+            targ.setAttribute(this.attribute, targ[e_prop].v);
+            targ[e_prop].v = null;
+        }
 
-/**
-  * @access private
-  */
-override function __LZfinalizeAnim( ) {
-    var e_prop = "e_" +  this.attribute;
-    if (!this.target[e_prop].c) { this.target[e_prop].c = 0; }
-    this.target[e_prop].c -= 1; //decrement animation counter for prop
-
-    if ( this.target[e_prop].c <= 0 ){
-        this.target[e_prop].c = 0;
-        this.target.setAttribute( this.attribute,this.target[e_prop].v);
-        this.target[e_prop].v = null;
+        this.__LZhalt();
     }
 
-    this.__LZhalt();
-}
+    /**
+      * This method calculates the next value of the parameter being animated. This
+      * method can be used by any Animator object that inherits from LzAnimator, as
+      * long as the parameter is a scalar value (i.e. a number instead of a point).
+      *
+      * @access private
+      *
+      * @param Number timeDifference: the time difference in milliseconds from the start
+      * of the animation.
+      * @return Number: the next value in the animations iteration sequence
+      */
+    function calcNextValue (timeDifference:Number) :Number {
+        // return the currentValue by default
+        var nextValue:Number = this.currentValue;
 
-/**
-  * This method calculates the next value of the parameter being animated. This
-  * method can be used by any Animator object that inherits from LzAnimator, as
-  * long as the parameter is a scalar value (i.e. a number instead of a point).
-  *
-  * @access private
-  *
-  * @param timeDifference: the time difference in milliseconds from the start
-  * of the animation.
-  * @return nextValue: the next value in the animations iteration sequence
-  */
-function calcNextValue( timeDifference ) {
-    // return the currentValue by default
-    var nextValue  = this.currentValue;
+        // create local references
+        var aEndPole:Number = this.endPole;
+        var aBeginPole:Number = this.beginPole;
 
-    // create local references
-    var aEndPole   = this.endPole;
-    var aBeginPole = this.beginPole;
+        // calculate new "K" value based on time difference
+        var K:Number = Math.exp((timeDifference * 1.0 / this.duration) * Math.log(this.primary_K));
 
-    // calculate new "K" value based on time difference
-    var K = Math.exp((timeDifference*1.0/this.duration)*
-                      Math.log(this.primary_K));
+        // calculate nextValue using the pole and new K value
+        if (K != 1.0) {
+           var aNumerator:Number = aBeginPole * aEndPole * (1 - K);
+           var aDenominator:Number = aEndPole - K * aBeginPole;
+           if (aDenominator != 0.0) nextValue = aNumerator / aDenominator;
+        }
+        return nextValue;
+    }
 
-    // calculate nextValue using the pole and new K value
-    if( K != 1.0 ) {
-       var aNumerator   = aBeginPole*aEndPole*(1 - K);
-       var aDenominator = aEndPole - K*aBeginPole;
-       if( aDenominator != 0.0 ) nextValue = aNumerator/aDenominator;
+    /**
+     * This method replaces the nonlinear calcNextValue when motion is set to linear
+     *
+     * @access private
+     * @return Number: the next value in the animations iteration sequence
+     */
+    function calcNextValueLinear (timeDifference:Number) :Number {
+        var elapsed:Number = timeDifference / this.duration;
+        return elapsed * this.to;
     }
-    return nextValue;
-}
 
-
-
-/**
- * This method replaces the nonlinear calcNextValue when motion is set to linear
-  *
-  * @access private
-  */
-function calcNextValueLinear( timeDifference ) {
-    var elapsed = timeDifference/this.duration;
-    return elapsed*this.to;
-}
-
-/**
-  * This is one of the core methods of an LzAnimator object. This method gets
-  * called to iterate the animation only once and then sets the property of the
-  * associated view.
-  *
-  * @access private
-  *
-  * @param time: the time assigned to this iteration of the animator. this time
-  * value ( in milliseconds) is set by the animation queue and then passed
-  * onto to every animator to ensure that all animators are synched to the same
-  * value.
-  * @return animatorIsDone: a boolean indicating if the animation is complete
-  */
-public override function update( time ) {
-    var animatorIsDone = false;
-
-    // If this is its first iteration then calc the necessary paramters.
-    // Calling this function here allows animators to be added to a queue at
-    // different times and then "synced" at start of execution, i.e. next onIdle
-    // event.
-    if ( this.doBegin ) {
-        this.beginAnimator( time );
-    } else {
-        if ( !this.paused ) {
-            var aTotalTimeDifference = time - this.startTime;
-            if ( aTotalTimeDifference < this.duration ) {
-                this.setValue( this.calcMethod( aTotalTimeDifference ));
-                this.lastIterationTime = time;
-            } else {
-                this.setValue( this.to );
-                return this.checkRepeat();
+    /**
+      * This is one of the core methods of an LzAnimator object. This method gets
+      * called to iterate the animation only once and then sets the property of the
+      * associated view.
+      *
+      * @access private
+      *
+      * @param Number time: the time assigned to this iteration of the animator. this time
+      * value (in milliseconds) is set by the animation queue and then passed
+      * onto to every animator to ensure that all animators are synched to the same
+      * value.
+      * @return Boolean: a boolean indicating if the animation is complete
+      */
+    override function update (time:Number) :Boolean {
+        // If this is its first iteration then calc the necessary paramters.
+        // Calling this function here allows animators to be added to a queue at
+        // different times and then "synced" at start of execution, i.e. next onIdle
+        // event.
+        if (this.doBegin) {
+            this.beginAnimator(time);
+        } else {
+            if (! this.paused) {
+                var aTotalTimeDifference:Number = time - this.startTime;
+                if (aTotalTimeDifference < this.duration) {
+                    this.setValue(this.calcMethod(aTotalTimeDifference));
+                    this.lastIterationTime = time;
+                } else {
+                    this.setValue(this.to);
+                    return this.checkRepeat();
+                }
             }
-         }
+        }
     }
-}
 
-/**
-  * sets the property specified in the binding to the <b>value</b>
-  *
-  * @access private
-  *
-  * @param value: to the value to be assigned
-  */
-function setValue( value ) {
-    // All animators are now relative at the core so add the difference
-    // of this value - the current value to the view's attribute.
-    var aDiff = value - this.currentValue;
-    if (this.target.setAttribute) {
-        //Debug.info('setValue', value, this.target);
-        this.target.setAttribute( this.attribute, this.target[this.attribute] + aDiff );
+    /**
+      * sets the property specified in the binding to the <b>value</b>
+      *
+      * @access private
+      *
+      * @param value: to the value to be assigned
+      */
+    function setValue (value:Number) :void {
+        // All animators are now relative at the core so add the difference
+        // of this value - the current value to the view's attribute.
+        var targ:LzNode = this.target;
+        var aDiff:Number = value - this.currentValue;
+        targ.setAttribute(this.attribute, targ[this.attribute] + aDiff);
+        this.currentValue = value;
     }
-    this.currentValue = value;
-}
 
+    /**
+      * @access private
+      */
+    override function toString() {
+        return "Animator for " + this.target + " attribute:" + this.attribute + " to:" + this.to;
+    }
 
-/**
-  * @access private
-  */
-override function toString(){
-    return "Animator for " + this.target + " attribute:" + this.attribute + " to:" + this.to;
-}
-
 } // End of LzAnimator
 
 lz[LzAnimator.tagname] = LzAnimator;  // publish

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LzAnimatorGroup.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LzAnimatorGroup.lzs	2008-10-15 08:00:11 UTC (rev 11452)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LzAnimatorGroup.lzs	2008-10-15 08:37:48 UTC (rev 11453)
@@ -13,7 +13,7 @@
   * <sgmltag class="element" role="LzAnimator">&lt;animator&gt;</sgmltag>s, and runs them in sequence or
   * simultaneously. As an example, the code below animates a view first
   * along the x-axis and then the y.</p>
-  *   
+  *
   * <example><programlisting class="code" extract="false">
   * &lt;canvas&gt;
   *   &lt;view bgcolor="red" width="100" height="100"&gt;
@@ -24,542 +24,564 @@
   *   &lt;/view&gt;
   * &lt;/canvas&gt;
   * </programlisting></example>
-  * 
+  *
   * <p>Any attribute that is legal in <sgmltag class="element" role="LzAnimator">&lt;animator&gt;</sgmltag> is legal
   * in <tagname>animatorgroup</tagname>. These attributes are then
   * cascaded to the animators contained within.</p>
-  * 
+  *
   * <p>Events (such as <event>onstart</event>, <event>onstop</event>,
   * etc.) and the <attribute>name</attribute> and
   * <attribute>id</attribute> attributes, however, are not cascaded.
   * Also, <attribute>start</attribute> defined at the group level is
   * effectively cascaded to the animators, meaning that the start
   * attribute is ignored in the animators themselves.</p>
-  * 
+  *
   * @lzxname animatorgroup
   * @shortdesc Coordinates the behavior of several animators.
   * @see LzAnimator
   *
   */
-dynamic class LzAnimatorGroup extends LzNode {
+public dynamic class LzAnimatorGroup extends LzNode {
 
-    function LzAnimatorGroup ( parent:* , attrs:* , children:* = null, instcall:*  = null) {
-        super(parent,attrs,children,instcall);
-    }  
+    /** @access private */
+    public function LzAnimatorGroup (parent:LzNode? = null, attrs:Object? = null, children:Array? = null, instcall:Boolean = false) {
+        super(parent, attrs, children, instcall);
+    }
 
-/** @access private
-  * @modifiers override 
-  */
-  static var tagname = 'animatorgroup';
-/** @access private */
-  static var attributes = new LzInheritedHash(LzNode.attributes);
+    /** @access private
+      * @modifiers override
+      */
+    static var tagname :String = 'animatorgroup';
+    /** @access private */
+    static var attributes :Object = new LzInheritedHash(LzNode.attributes);
 
-  /** The name of the attribute whose value is animated.  This
-    * attribute is required on an animator, unless the animator is
-    * inside an animatorgroup that specifies an attribute.
-    *
-    * @type String
-    * @lzxtype token
-    */
-  var attribute;
+    /** @access private */
+    var updateDel :LzDelegate;
+    /** @access private */
+    var crepeat :Number;
+    /** @access private */
+    var startTime :Number;
+    /** @access private */
+    var __LZpauseTime :Number;
+    /** @access private */
+    var actAnim :Array;
+    /** @access private */
+    var notstarted :Boolean;
+    /** @access private */
+    var needsrestart :Boolean;
 
-    var updateDel;
-    var crepeat;
-    var startTime;
-/** @access private */
-    var __LZpauseTime;
-    var actAnim;
+    /** The name of the attribute whose value is animated.  This
+      * attribute is required on an animator, unless the animator is
+      * inside an animatorgroup that specifies an attribute.
+      *
+      * @type String
+      * @lzxtype token
+      */
+    var attribute;
 
+    /** Whether to start the animation instantly (the default),
+      * or wait for a script command.
+      *
+      * @type Boolean
+      * @lzxtype boolean
+      * @lzxdefault "true"
+      */
+    var start = true;
+    LzAnimatorGroup.attributes.start = true;
 
-  /** Whether to start the animation instantly (the default),
-    * or wait for a script command.
-    *
-    * @type Boolean
-    * @lzxtype boolean
-    * @lzxdefault "true"
-    */
-  var start = true;
-  LzAnimatorGroup.attributes.start = true;
-  
-  /** The start value for the animation.  Defaults to the
-    * targeted attribute's current value.
-    * @type Number
-    * @lzxtype number
-    */
-  var from;
-  
-  /** The final value for the targeted attribute.
-    *
-    * @type Number
-    * @lzxtype number
-    */
-  var to;
-  
-  /** The duration of the animation, in milliseconds (1000 = 1 second).
-    *
-    * @type Number
-    * @lzxtype xsd:float {minInclusive="0"} | constraint
-    */
-  var duration;
-  
-  /** 
-    * @type Boolean
-    * @lzxtype boolean
-    * @since 1.1
-    */
-  var indirect = false;
-  
-  /** Whether the to value is relative to the initial value of the
-    * attribute (<constant>true</constant>), or is absolute (<constant>false</constant>).
-    *
-    * @type Boolean
-    * @lzxtype boolean
-    * @lzxdefault "false"
-    */
-  var relative = false;
-  
-  /** One of "linear" | "easein" | "easeout" | "easeboth"
-    * @type String
-    * @lzxtype token
-    */
-  var motion = "easeboth";
-  
-  /** The number of times to repeat the animation.  This should be a
-    * positive integer, or 'Infinity'.  Changes to the repeat value
-    * take effect, after the animation is finished and then restarted.
-    *
-    * @type Object
-    * @lzxtype expression
-    * @since 1.1
-    */
-  var repeat;
-  
-  /** The paused state of the animator. If true, the animator will stop. When
-    * changed to false, the animator will resume from its current location.
-    *
-    * @type Boolean
-    * @lzxtype boolean
-    * @lzxdefault "false"
-    */
-  var paused = false;
-  /**
-   * Setter for paused
-   * @access private
-   */
-  function $lzc$set_paused (val) {
-    this.pause(val);
-  }
+    /** The start value for the animation.  Defaults to the
+      * targeted attribute's current value.
+      * @type Number
+      * @lzxtype number
+      */
+    var from;
 
-  /** Value of the animator's start attribute.
-    *
-    * @type Boolean
-    */
-  var started;
-  
-  /** the object for which an attribute will be animated (by default, this
-    * is the immediateParent)
-    *
-    * @type String
-    * @lzxtype reference
-    */
-  var target;
-  
-  /** <dl><dt>"simultaneous" or none</dt><dd>means process animators
-    * simultaneously</dd>
-    * <dt>"sequential"</dt><dd>means process animators
-    * sequentially;</dd></dl>
-    *
-    * Animators other than animatorgroups ignore this attribute
-    *
-    * @type string
-    */
-  var process = "sequential";
-  
+    /** The final value for the targeted attribute.
+      *
+      * @type Number
+      * @lzxtype number
+      */
+    var to;
 
-/** The active-state of the animator. If true, the animator is currently processing its animation.
-   * This field is read-only.
-   *
-   * @type Boolean
-   * @lzxtype boolean
-   * @modifier read-only
-   */
-  var isactive = false;
-/** @lzxtype event */
-var ontarget = LzDeclaredEvent;
-/** @lzxtype event */
-var onduration = LzDeclaredEvent;
-/** @lzxtype event */
-var onstarted = LzDeclaredEvent;
+    /** The duration of the animation, in milliseconds (1000 = 1 second).
+      *
+      * @type Number
+      * @lzxtype xsd:float {minInclusive="0"} | constraint
+      */
+    var duration;
 
-/** Executed when the animator starts.  This code is executed
-  * multiple times if the animator repeats.
-  * @lzxtype event
-  */
-var onstart = LzDeclaredEvent;
-/** @lzxtype event */
-var onpaused = LzDeclaredEvent;
+    /**
+      * @type Boolean
+      * @lzxtype boolean
+      * @since 1.1
+      */
+    var indirect = false;
 
-/** Use of 'onfinish' event
-  * is deprecated. Use 'onstop' event instead.
-  * @keywords deprecated
-  * @lzxtype event
-  */
-var onfinish = LzDeclaredEvent;
+    /** Whether the to value is relative to the initial value of the
+      * attribute (<constant>true</constant>), or is absolute (<constant>false</constant>).
+      *
+      * @type Boolean
+      * @lzxtype boolean
+      * @lzxdefault "false"
+      */
+    var relative = false;
 
-/** Executed when the animator finishes.
-  * @lzxtype event
-  */
-var onstop = LzDeclaredEvent;
+    /** One of "linear" | "easein" | "easeout" | "easeboth"
+      * @type String
+      * @lzxtype token
+      */
+    var motion = "easeboth";
 
-/** Event sent at the beginning of each new repeat. 
-  * @lzxtype event 
-  */
-var onrepeat = LzDeclaredEvent;
+    /** The number of times to repeat the animation.  This should be a
+      * positive integer, or 'Infinity'.  Changes to the repeat value
+      * take effect, after the animation is finished and then restarted.
+      *
+      * @type Number
+      * @lzxtype number
+      * @lzxdefault 1
+      * @since 1.1
+      */
+    var repeat = 1;
 
-var animatorProps = { attribute : true, from : true ,
-                      duration : true , to : true ,
-                      relative : true , target : true}
-
-/** animators ignore placement by default 
-  *
-  * @modifiers override
-  */
-LzAnimatorGroup.attributes.ignoreplacement = true;
-
-/**
-  * @access private
-  */
-override function construct ( parent, args ) {
-
-    super.construct.apply(this, arguments);
-
-    if ( (this.immediateparent) is ( LzAnimatorGroup ) ){
-        for ( var k in this.animatorProps ){
-            if ( args[ k ] == null ){
-                args[ k ] = this.immediateparent[ k ] ;
+    /**
+      * Setter for repeat
+      * @access private
+      */
+    function $lzc$set_repeat (val) {
+        if (val <= 0) {
+            // NOTE: (LPP-7153) for bwcomp we convert values <= 0 to Infinity, 
+            // issue a warning so users can upgrade their code to use the proper form
+            // TODO: [20081011 anba] remove bwcomp-mode after 4.3+
+            if ($debug) {
+                Debug.info("%w.%s: value was <= 0, use Infinity instead", this, arguments.callee);
             }
+            val = Infinity;
         }
-        if ( this.immediateparent.animators == null ){
-            this.immediateparent.animators = [ this ];
-        } else {
-           this.immediateparent.animators.push( this );
-        }
-        args.start = LzNode._ignoreAttribute;
-    } else {
-        // initialize target to immediateparent, may be set later by attribute
-        this.target = this.immediateparent;
+        this.repeat = val;
     }
 
-    if (! this.updateDel) this.updateDel = new LzDelegate( this , "update" );
-}
+    /** The paused state of the animator. If true, the animator will stop. When
+      * changed to false, the animator will resume from its current location.
+      *
+      * @type Boolean
+      * @lzxtype boolean
+      * @lzxdefault "false"
+      */
+    var paused = false;
 
-/**
-  * @access private
-  */
-override function init ( ) {
-    if (! this.target) this.target = this.immediateparent;
-    if ( this.started ) this.doStart();
-    super.init.apply(this, arguments);
-}
-
-/**
-  * setter for the target attribute
-  * @access private
-  */
-function $lzc$set_target ( new_target ){
-    this.target = new_target;
-    var nodes = this.subnodes;
-    if (nodes) {
-        for (var i=0; i < nodes.length; i++) {
-            if ((nodes[i]) is ( LzAnimatorGroup )) {
-                nodes[i].$lzc$set_target(new_target);
-            }
-        }
+    /**
+      * Setter for paused
+      * @access private
+      */
+    function $lzc$set_paused (val) {
+        this.pause(val);
     }
-    if (this.ontarget.ready) this.ontarget.sendEvent( new_target );
-}
 
-/** Remove after 4.1
- * @deprecated Use setAttribute('target', ...) instead.
- * @access private */
-final function setTarget (n) {
-  if ($debug) {
-    Debug.deprecated(this, arguments.callee, this.setAttribute);
-  }
-  this.$lzc$set_target(n);
-}
+    /** Value of the animator's start attribute.
+      *
+      * @type Boolean
+      * @lzxtype boolean
+      */
+    var started;
 
+    /** the object for which an attribute will be animated (by default, this
+      * is the immediateParent)
+      *
+      * @type String
+      * @lzxtype reference
+      */
+    var target;
 
-/**
-  * setter for the start attribute
-  * @access private
-  */
-function $lzc$set_start ( start ){
-    this.started = start;
-    if (this.onstarted.ready) this.onstarted.sendEvent( start );
-    if ( !this.isinited ){
-        return;
-    }
+    /** <dl><dt>"simultaneous" or none</dt><dd>means process animators
+      * simultaneously</dd>
+      * <dt>"sequential"</dt><dd>means process animators
+      * sequentially;</dd></dl>
+      *
+      * Animators other than animatorgroups ignore this attribute
+      *
+      * @type String
+      * @lzxtype string
+      */
+    var process = "sequential";
 
-    if ( start ) {
-        this.doStart();
-    } else {
-        this.stop();
-    }
+    /** The active-state of the animator. If true, the animator is currently processing its animation.
+      * This field is read-only.
+      *
+      * @type Boolean
+      * @lzxtype boolean
+      * @modifier read-only
+      */
+    var isactive :Boolean = false;
 
-}
+    /** @lzxtype event */
+    var ontarget :LzDeclaredEventClass = LzDeclaredEvent;
 
-/**
-  * called to set starting flags and values, send onstart event, and register
-  * animator for processing on the main idle loop.
-  */
-function doStart (){
-    if ( this.isactive ) return false;
+    /** @lzxtype event */
+    var onduration :LzDeclaredEventClass = LzDeclaredEvent;
 
-    // update the views counter of animation currently executing
-    //this.target.anmExecuteCount += 1;
+    /** @lzxtype event */
+    var onstarted :LzDeclaredEventClass = LzDeclaredEvent;
 
-    //Debug.info('doStart', start);
-    if (this.onstart.ready) this.onstart.sendEvent( (new Date()).getTime() );
-    //this is a bug -- embedded animators won't send onstart
+    /** Executed when the animator starts.  This code is executed
+      * multiple times if the animator repeats.
+      * @lzxtype event
+      */
+    var onstart :LzDeclaredEventClass = LzDeclaredEvent;
 
-    this.isactive = true;
+    /** @lzxtype event */
+    var onpaused :LzDeclaredEventClass = LzDeclaredEvent;
 
-    // store a copy of repeat for decrementing after each iteration
-    this.crepeat = this.repeat;
+    /** Executed when the animator finishes.
+      * @lzxtype event
+      */
+    var onstop :LzDeclaredEventClass = LzDeclaredEvent;
 
-    this.prepareStart();
-    this.updateDel.register( lz.Idle , "onidle" );
-    return true;
-}
+    /** Event sent at the beginning of each new repeat.
+      * @lzxtype event
+      */
+    var onrepeat :LzDeclaredEventClass = LzDeclaredEvent;
 
-/**
-  * @access private
-  */
-function prepareStart ( ){
-    for ( var i = this.animators.length-1; i >=0 ; i-- ){
-        this.animators[ i ].notstarted = true;
-        //this.animators[ i ].prepareStart();
-    }
-    this.actAnim = this.animators.concat();
-}
+    /** @access private */
+    const animatorProps :Object = { attribute : true, from : true,
+                                     duration : true, to : true,
+                                     relative : true, target : true }
 
-/**
-  * @access private
-  */
-function resetAnimator ( ){
-     this.actAnim = this.animators.concat();
-    // this.prepareStart();
-    for ( var i = this.animators.length-1; i >=0 ; i-- ){
-       this.animators[ i ].needsrestart = true;
-       //this.animators[ i ].resetAnimator();
-    }
+    /** animators ignore placement by default
+      *
+      * @modifiers override
+      */
+    LzAnimatorGroup.attributes.ignoreplacement = true;
 
-}
+    /**
+      * @access private
+      */
+    override function construct (parent, args) {
+        super.construct(parent, args);
 
+        var ip:LzNode = this.immediateparent;
+        if (ip is LzAnimatorGroup) {
+            for (var k:String in this.animatorProps) {
+                // FIXME: [20081011 anba] (LPP-2222) this logic doesn't
+                // work well with user-defined animator(groups)
+                if (args[ k ] == null) {
+                    args[ k ] = ip[ k ];
+                }
+            }
+            if (ip.animators == null) {
+                ip.animators = [ this ];
+            } else {
+               ip.animators.push(this);
+            }
+            args.start = LzNode._ignoreAttribute;
+        } else {
+            // initialize target to immediateparent, may be set later by attribute
+            this.target = ip;
+        }
 
-/**
-  * in order to repeat an animtorGroup its animators cannot be deleted from the
-  * animator array.
-  *
-  * @access private
-  *
-  * @param time: the time assigned to this iteration of the animator. this time
-  * value ( in milliseconds) is set by the animation queue and then passed
-  * onto to every animator to ensure that all animators are synched to the same
-  * value.
-  * @return a boolean indicating if all of the animations within
-  * this group are done.
-  */
-public function update( time ) {
-    var animend = this.actAnim.length -1;
-    if (animend > 0 && this.process == "sequential")
-        animend = 0;
+        if (! this.updateDel) this.updateDel = new LzDelegate(this, "update");
+    }
 
-    if ( this.paused ) {
-        return;
+    /**
+      * @access private
+      */
+    override function init () {
+        if (! this.target) this.target = this.immediateparent;
+        if (this.started) this.doStart();
+        super.init();
     }
 
-    for (var i = animend; i >= 0 ; i-- ) {
-        var a = this.actAnim[i];
-        //if ( this.process == "simultaneous" ) Debug.write( "call " + a );
-        if (a.notstarted) {
-            a.isactive = true;
-            a.prepareStart();
-            a.notstarted = false;
-        } else if (a.needsrestart) {
-            a.resetAnimator();
-            a.needsrestart = false;
+    /**
+      * setter for the target attribute
+      * @access private
+      */
+    function $lzc$set_target (new_target) {
+        this.target = new_target;
+        var nodes:Array = this.subnodes;
+        if (nodes) {
+            for (var i:int = 0; i < nodes.length; i++) {
+                if (nodes[i] is LzAnimatorGroup) {
+                    nodes[i].$lzc$set_target(new_target);
+                }
+            }
         }
+        if (this.ontarget.ready) this.ontarget.sendEvent(new_target);
+    }
 
-        if ( a.update( time ) ) {
-             //a.stop(); //OK?
-            this.actAnim.splice( i, 1 );
+    /** Remove after 4.1
+     * @deprecated Use setAttribute('target', ...) instead.
+     * @access private */
+    final function setTarget (n) {
+        if ($debug) {
+            Debug.deprecated(this, arguments.callee, this.setAttribute);
         }
-
+        this.$lzc$set_target(n);
     }
-    //if ( this.process == "simultaneous" ) Debug.write( "done this round" );
 
-    if ( ! this.actAnim.length ) {
-        return this.checkRepeat();
+    /**
+      * setter for the start attribute
+      * @access private
+      */
+    function $lzc$set_start (start) {
+        this.started = start;
+        if (this.onstarted.ready) this.onstarted.sendEvent(start);
+        if (! this.isinited) {
+            return;
+        }
+
+        if (start) {
+            this.doStart();
+        } else {
+            this.stop();
+        }
     }
-    return false;
-}
 
-/**
-  * Temporarily pauses or restarts the animator
-  * @param Boolean dop: If true, pauses the animator. If false, unpauses the
-  * animator. If null, toggles the paused state of the animator.
-  */
-function pause ( dop = null){
-    if ( dop == null ){
-        dop = !this.paused;
+    /**
+      * Called to set starting flags and values, send onstart event, and register
+      * animator for processing on the main idle loop.
+      */
+    function doStart () {
+        if (this.isactive) return false;
+
+        // update the views counter of animation currently executing
+        //this.target.anmExecuteCount += 1;
+
+        //Debug.info('doStart', start);
+        if (this.onstart.ready) this.onstart.sendEvent(new Date().getTime());
+        //this is a bug -- embedded animators won't send onstart
+
+        this.isactive = true;
+
+        // store a copy of repeat for decrementing after each iteration
+        this.crepeat = this.repeat;
+
+        this.prepareStart();
+        this.updateDel.register(lz.Idle , "onidle");
+        return true;
     }
 
-    if ( this.paused && ! dop ){
-        this.__LZaddToStartTime( ((new Date()).getTime()) - this.__LZpauseTime );
-    } else if (! this.paused && dop ){
-        this.__LZpauseTime = ((new Date()).getTime());
+    /**
+      * @access private
+      */
+    function prepareStart () :void {
+        for (var i:int = this.animators.length - 1; i >= 0; i--) {
+            this.animators[ i ].notstarted = true;
+            //this.animators[ i ].prepareStart();
+        }
+        this.actAnim = this.animators.concat();
     }
 
-    this.paused = dop;
-    if (this.onpaused.ready) this.onpaused.sendEvent( dop );
-}
-
-/**
-  * @access private
-  */
-function __LZaddToStartTime( ptime ) {
-    this.startTime += ptime;
-    for ( var i = 0 ; i < this.actAnim.length ; i++ ){
-        this.actAnim[ i ].__LZaddToStartTime( ptime );
+    /**
+      * @access private
+      */
+    function resetAnimator () :void {
+        this.actAnim = this.animators.concat();
+        // this.prepareStart();
+        for (var i:int = this.animators.length - 1; i >= 0; i--) {
+            this.animators[ i ].needsrestart = true;
+            //this.animators[ i ].resetAnimator();
+        }
     }
-}
 
-/**
-  * Stop is called when the animation is complete, or when the animator is
-  * destroyed. It can also be called to halt a running animation.
-  */
-function stop( ) {
+    /**
+      * in order to repeat an animtorGroup its animators cannot be deleted from the
+      * animator array.
+      *
+      * @access private
+      *
+      * @param time: the time assigned to this iteration of the animator. this time
+      * value (in milliseconds) is set by the animation queue and then passed
+      * onto to every animator to ensure that all animators are synched to the same
+      * value.
+      * @return a boolean indicating if all of the animations within
+      * this group are done.
+      */
+    function update (time:Number) :Boolean {
+        if (this.paused) {
+            return;
+        }
 
-    //need to stop any running animators
-    if (this.actAnim) {
-        var animend = this.actAnim.length -1;
+        var animend:int = this.actAnim.length - 1;
         if (animend > 0 && this.process == "sequential")
             animend = 0;
 
-        for (var i = animend; i >= 0 ; i-- ) {
-            this.actAnim[i].stop();
+        for (var i:int = animend; i >= 0; i--) {
+            var a:LzAnimatorGroup = this.actAnim[i];
+            if (a.notstarted) {
+                a.isactive = true;
+                a.prepareStart();
+                a.notstarted = false;
+            } else if (a.needsrestart) {
+                a.resetAnimator();
+                a.needsrestart = false;
+            }
+
+            if (a.update(time)) {
+                 //a.stop(); //OK?
+                this.actAnim.splice(i, 1);
+            }
         }
+
+        if (! this.actAnim.length) {
+            return this.checkRepeat();
+        }
+        return false;
     }
 
-    this.__LZhalt();
-}
+    /**
+      * Temporarily pauses or restarts the animator
+      * @param Boolean dop: If true, pauses the animator. If false, unpauses the
+      * animator. If null, toggles the paused state of the animator.
+      */
+    function pause (dop = null) {
+        if (dop == null) {
+            dop = !this.paused;
+        }
 
+        if (this.paused && ! dop) {
+            this.__LZaddToStartTime(new Date().getTime() - this.__LZpauseTime);
+        } else if (! this.paused && dop) {
+            this.__LZpauseTime = new Date().getTime();
+        }
 
-/** Remove after 4.1
- * @deprecated Use setAttribute('duration', ...) instead.
- * @access private */
-final function setDuration(duration){
-  if ($debug) {
-    Debug.deprecated(this, arguments.callee, this.setAttribute);
-  }
-  this.$lzc$set_duration(duration);
-}
-/** @access private */
-function $lzc$set_duration (duration) {
-    if(isNaN(duration) || duration == null){
-        duration = 0;
-    } else if(typeof(duration) == "string"){
-        duration = Number(duration);
+        this.paused = dop;
+        if (this.onpaused.ready) this.onpaused.sendEvent(dop);
     }
-    this.duration = duration;
-    if(!(this is LzAnimator)){
-        var sn = this.subnodes;
-        if(sn){
-            for(var i = 0; i < sn.length; ++i){
-                if(sn[i] is LzAnimatorGroup){
-                    sn[i].setAttribute('duration', duration);
-                }
+
+    /**
+      * @access private
+      */
+    function __LZaddToStartTime (ptime:Number) :void {
+        this.startTime += ptime;
+        for (var i:int = 0; i < this.actAnim.length; i++) {
+            this.actAnim[ i ].__LZaddToStartTime(ptime);
+        }
+    }
+
+    /**
+      * Stop is called when the animation is complete, or when the animator is
+      * destroyed. It can also be called to halt a running animation.
+      */
+    function stop () {
+        //need to stop any running animators
+        if (this.actAnim) {
+            var animend:int = this.actAnim.length - 1;
+            if (animend > 0 && this.process == "sequential")
+                animend = 0;
+
+            for (var i:int = animend; i >= 0; i--) {
+                this.actAnim[i].stop();
             }
         }
+
+        this.__LZhalt();
     }
-    this.onduration.sendEvent(duration);
-}
 
-/**
-  * @access private
-  */
-function __LZfinalizeAnim (){
-    this.__LZhalt();
-}
+    /** Remove after 4.1
+     * @deprecated Use setAttribute('duration', ...) instead.
+     * @access private */
+    final function setDuration (duration) {
+        if ($debug) {
+            Debug.deprecated(this, arguments.callee, this.setAttribute);
+        }
+        this.$lzc$set_duration(duration);
+    }
 
-/**
-  * @access private
-  */
-function __LZhalt (){
-    this.isactive = false;
-    //unreg for update event
-    this.updateDel.unregisterAll();
-    if (this.onfinish.ready) this.onfinish.sendEvent( this );
-    if (this.onstop.ready) this.onstop.sendEvent( (new Date()).getTime() );
-}
+    /** @access private */
+    function $lzc$set_duration (duration) {
+        if (isNaN(duration)) {
+            duration = 0;
+        } else {
+            duration = Number(duration);
+        }
+        this.duration = duration;
+        var sn:Array = this.subnodes;
+        if (sn) {
+            for (var i:int = 0; i < sn.length; ++i) {
+                if (sn[i] is LzAnimatorGroup) {
+                    sn[i].$lzc$set_duration(duration);
+                }
+            }
+        }
+        this.onduration.sendEvent(duration);
+    }
 
-/**
-  * @access private
-  */
-function checkRepeat (){
-    if ( this.crepeat == null || this.crepeat == 1) {
-        this.__LZfinalizeAnim();
-        return true;
+    /**
+      * @access private
+      */
+    function __LZfinalizeAnim () :void {
+        this.__LZhalt();
     }
 
-    if ( this.crepeat > 0 ) {
-        this.crepeat--;
-        if (this.onrepeat.ready) this.onrepeat.sendEvent( (new Date()).getTime() );
+    /**
+      * @access private
+      */
+    function __LZhalt () :void {
+        this.isactive = false;
+        //unreg for update event
+        this.updateDel.unregisterAll();
+        if (this.onstop.ready) this.onstop.sendEvent(new Date().getTime());
     }
-    //this.prepareStart();
-    this.resetAnimator();
-}
 
-/**
-  * @access private
-  */
-override function destroy( ) {
-    this.stop();
-    this.updateDel.unregisterAll();
-    this.animators = null;
-    this.actAnim = null;
+    /**
+      * @access private
+      */
+    function checkRepeat () :Boolean {
+        if (this.crepeat == 1) {
+            this.__LZfinalizeAnim();
+            return true;
+        } else {
+            this.crepeat--;
+            if (this.onrepeat.ready) this.onrepeat.sendEvent(new Date().getTime());
+            //this.prepareStart();
+            this.resetAnimator();
+        }
+    }
 
-    if ( this.parent.animators && this.parent.animators.length){
-            for ( var i = 0 ; i < this.parent.animators.length ; i++ ){
-                if ( this.parent.animators[ i ] == this ){
-                    this.parent.animators.splice( i , 1 );
+    /**
+      * @access private
+      */
+    override function destroy () {
+        this.stop();
+        this.updateDel.unregisterAll();
+        this.animators = null;
+        this.actAnim = null;
+
+        var ip:LzNode = this.immediateparent;
+        var parAnim:Array = ip.animators;
+        if (parAnim && parAnim.length) {
+            for (var i:int = 0; i < parAnim.length; i++) {
+                if (parAnim[ i ] == this) {
+                    parAnim.splice(i, 1);
                     break;
                 }
             }
 
-    for ( var i = 0 ; i < LzAnimatorGroup(this.parent).actAnim.length ; i++ ){
-        if ( LzAnimatorGroup(this.parent).actAnim[ i ] == this ){
-            LzAnimatorGroup(this.parent).actAnim.splice( i , 1 );
-                break;
+            if (ip is LzAnimatorGroup) {
+                var activeAnim:Array = (ip cast LzAnimatorGroup).actAnim;
+                if (activeAnim && activeAnim.length) {
+                    for (var i:int = 0; i < activeAnim.length; i++) {
+                        if (activeAnim[ i ] == this) {
+                            activeAnim.splice(i, 1);
+                            break;
+                        }
+                    }
+                }
             }
         }
+
+        super.destroy();
     }
 
-    super.destroy();
-}
+    /**
+      * @access private
+      */
+    override function toString () {
+        if (this.animators) {
+            return "Group of " + this.animators.length;
+        }
+        return "Empty group";
+    }
 
-/**
-  * @access private
-  */
-override function toString(  ) {
-  if (this.animators) {
-    return "Group of " + this.animators.length;
-  }
-  return "Empty group";
-}
-
 } // End of LzAnimatorGroup
 
 lz[LzAnimatorGroup.tagname] = LzAnimatorGroup;  // publish



More information about the Laszlo-checkins mailing list