/** * Timer.as - Timing Management * * Copyright (c) 2004, 2112 F/X. All Rights Reserved. For educational use only. Commercial use strictly prohibited. * * This software program is supplied 'as is' without any warranty, express, implied, * or otherwise, including without limitation all warranties of merchantability or fitness * for a particular purpose. 2112 F/X shall not be liable for any special * incidental, or consequential damages, including, without limitation, lost * revenues, lost profits, or loss of prospective economic advantage, resulting * from the use or misuse of this software program. * * @author Jim Armstrong * @version 1.0 */ import mx.events.EventDispatcher; import mx.utils.Delegate; import mx.controls.Label; class Timer { static var DISPLAY:Boolean = true; static var NO_DISPLAY:Boolean = false; static var COUNT_UP:Boolean = true; static var COUNT_DOWN:Boolean = false; // core private var __target:Number; // Target time in seconds before dispatching event private var __delta:Number; // Delta (in seconds) since start operation private var __startTime:Number; // Start time in milliseconds private var __stamp:Boolean; // true if time stamp is updated private var __id:Number; // numerical ID associated with a timing event private var __countUp:Boolean; // true if counting up, false if counting down // Timer and time stamp private var __stampClip:MovieClip; // clip that contains time stamp Label private var __timeStamp:Label; // Label component containing time stamp string, H:MM:SS private var __location:pair; // coordinates of ULC of time stamp // Functions private var __updateTimer:Function; private var __dUpdateTimer:Function; // Exception private var __e:Exception; // Events dispatched by this class private var dispatchEvent:Function; var addEventListener:Function; var removeEventListener:Function; public function Timer(_mc:MovieClip, _d:Number) { EventDispatcher.initialize(this); __e = new Exception(); __e.className = "Timer"; __e.errorLevel = Exception.FATAL; __e.methodName = "Timer()"; if ( _mc == undefined || _mc == null ) { __e.errorMessage = "Invalid parent reference"; throw __e; } if( _d == undefined || _d <= 0 ) { __e.errorMessage = "Invalid depth"; throw __e; } __stampClip = _mc.createEmptyMovieClip( "stampClip", _d ); __timeStamp = Label(__stampClip.createClassObject(Label , "timestamp", 2, {text:""})); if( __timeStamp == undefined ) { __e.errorMessage = "Unable to create time stamp Label"; throw __e; } __init(); } private function __init(Void):Void { __target = -1.0; __delta = 0.0; __startTime = 0.0; __id = 0; __stamp = false; __countUp = true; __location = new pair(0,0); __handlers(); } public function get target():Number { return __target; } public function get id():Number { return __id; } public function set id(_n:Number) { __id = _n; } public function set target(_t:Number):Void { __e.methodName = "target()"; if ( _t < 0 ) { __e.errorMessage = "Invalid target time: " + _t.toString(); throw __e; } __target = _t; } public function set loc(_p:pair) { if ( _p.first != undefined ) __location.first = _p.first; if ( _p.second != undefined ) __location.second = _p.second; } private function __handlers(Void):Void { // Suggestion -- what about adding fractions of seconds to the timestamp? __updateTimer = function(Void):Void { __delta = 0.001*(getTimer() - __startTime); // update time stamp if ( __stamp ) { var hours:Number = 0; var remainder:Number = 0; var minutes:Number = 0; var seconds:Number = 0; if ( __countUp ) { var hours:Number = Math.floor(__delta*0.00027777777777777); var remainder:Number = __delta - hours*3600.0; var minutes:Number = Math.floor(remainder*0.0166666666666666667); var seconds:Number = Math.floor(remainder - minutes*60); } else { var count:Number = __target - __delta; var hours:Number = Math.round(count*0.00027777777777777); var remainder:Number = count - hours*3600.0; var minutes:Number = Math.round(remainder*0.0166666666666666667); var seconds:Number = Math.round(remainder - minutes*60); } var stamp:String = (hours.toString() + ":"); if ( minutes < 10 ) { if ( hours > 0 ) stamp += ("0" + minutes.toString() + ":"); else stamp += (minutes.toString() + ":"); } else stamp += (minutes.toString() + ":"); if ( seconds < 10 ) stamp += ("0" + seconds.toString()); else stamp += seconds.toString(); __timeStamp.text = stamp; } // test if target delta has been met or exceeded if ( __delta >= __target ) __completed(); }; __dUpdateTimer = Delegate.create( this, __updateTimer ); } /** * @description Method: start(_s:Boolean, _c:Boolean) - Begin a new timer session. * * NOTE: A timing sesstion may not be started until a strictly positive target time * has been assigned. * * @param _s:Boolean - true if time stamp is to be displayed. false or undefined otherwise * @param _c:Boolean - true if count-up, false if count-down * * @return Nothing * * @since 1.0 * */ public function start(_s:Boolean, _c:Boolean):Void { __e.methodName = "start()"; if ( __target <= 0 ) { __e.errorMessage = "Assign a target time before starting timer"; throw __e; } if ( _s != undefined ) { __stamp = _s; if ( _c != undefined ) __countUp = _c else __countUp = false; } else __stamp = false; // position the time stamp __timeStamp.move( __location.first, __location.second ); // clear stamp __timeStamp.text = ""; // assign onEnterFrame handler for the time stamp __stampClip.onEnterFrame = __dUpdateTimer; __stampClip._visible = true; // start timing ... __startTime = getTimer(); // fire 'onStart' event dispatchEvent( {target:__target, type:"onStart"} ); } private function __completed(Void):Void { delete __stampClip.onEnterFrame; __stampClip._visible = false; // fire 'onComplete' event with current ID dispatchEvent( {target:this, type:"onComplete", id:__id, delta:__delta} ); } }