I need a simple digital clock, but did not find any such standard component. Then using Timer and Date class I tried to create a Digital Clock in ActionScript.
I used Timer and Date class to implement this clock. The clock also has the functionality to dispatch events for (every second, every minute, every hour). This clock can be extended to add other functionality as well.
First of all we have event class as:
package mittal.events
{
import flash.events.Event;
/**
* The DigitalClockEvent class represents event objects
* that are dispatched by Digital Clock component when second, minute, hour changes
* or any such activity happens.
*
* @see mittal.components.DigitalClock
*
* @langversion 3.0
* @productversion Flex 4
*/
public class DigitalClockEvent extends Event
{
/**
* The <code>DigitalClockEvent.CLOCK_START</code> constant defines the value of the
* <code>type</code> property of the event object for a <code>clockStart</code> event.
*
* <p>The properties of the event object have the following values:</p>
* <table class="innertable">
* <tr><th>Property</th><th>Value</th></tr>
* <tr><td><code>bubbles</code></td><td>false</td></tr>
* <tr><td><code>cancelable</code></td><td>true</td></tr>
* </table>
*
* @eventType clockStart
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public static const CLOCK_START:String = "clockStart";
/**
* The <code>DigitalClockEvent.CLOCK_STOP</code> constant defines the value of the
* <code>type</code> property of the event object for a <code>clockStop</code> event.
*
* <p>The properties of the event object have the following values:</p>
* <table class="innertable">
* <tr><th>Property</th><th>Value</th></tr>
* <tr><td><code>bubbles</code></td><td>false</td></tr>
* <tr><td><code>cancelable</code></td><td>true</td></tr>
* </table>
*
* @eventType clockStop
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public static const CLOCK_STOP:String = "clockStop";
/**
* The <code>DigitalClockEvent.SECOND_OVER</code> constant defines the value of the
* <code>type</code> property of the event object for a <code>clockTick</code> event.
*
* <p>The properties of the event object have the following values:</p>
* <table class="innertable">
* <tr><th>Property</th><th>Value</th></tr>
* <tr><td><code>bubbles</code></td><td>false</td></tr>
* <tr><td><code>cancelable</code></td><td>true</td></tr>
* </table>
*
* @eventType secondOver
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public static const SECOND_OVER:String = "secondOver";
/**
* The <code>DigitalClockEvent.MINUTE_OVER</code> constant defines the value of the
* <code>type</code> property of the event object for a <code>minuteOver</code> event.
*
* <p>The properties of the event object have the following values:</p>
* <table class="innertable">
* <tr><th>Property</th><th>Value</th></tr>
* <tr><td><code>bubbles</code></td><td>false</td></tr>
* <tr><td><code>cancelable</code></td><td>true</td></tr>
* </table>
*
* @eventType minuteOver
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public static const MINUTE_OVER:String = "minuteOver";
/**
* The <code>DigitalClockEvent.MINUTE_OVER</code> constant defines the value of the
* <code>type</code> property of the event object for a <code>minuteOver</code> event.
*
* <p>The properties of the event object have the following values:</p>
* <table class="innertable">
* <tr><th>Property</th><th>Value</th></tr>
* <tr><td><code>bubbles</code></td><td>false</td></tr>
* <tr><td><code>cancelable</code></td><td>true</td></tr>
* </table>
*
* @eventType hourOver
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public static const HOUR_OVER:String = "hourOver";
/**
* The <code>DigitalClockEvent.DAY_OVER</code> constant defines the value of the
* <code>type</code> property of the event object for a <code>minuteOver</code> event.
*
* <p>The properties of the event object have the following values:</p>
* <table class="innertable">
* <tr><th>Property</th><th>Value</th></tr>
* <tr><td><code>bubbles</code></td><td>false</td></tr>
* <tr><td><code>cancelable</code></td><td>true</td></tr>
* </table>
*
* @eventType dayOver
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public static const DAY_OVER:String = "dayOver";
public function DigitalClockEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
/**
* @private
*/
override public function clone():Event
{
return new DigitalClockEvent(type, bubbles, cancelable);
}
}
}
The main logic is performed by the component class. This class extends Spark label to show the time and also provides various features like set time/hour/minute/seconds; dispatch events on minute over, second over, hour over etc; also provide a way to suppress these events if necessary.
package mittal.components
{
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
import mittal.events.DigitalClockEvent;
import spark.components.Label;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the clock starts.
*
* @eventType mittal.events.DigitalClockEvent.CLOCK_START
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[Event(name="clockStart", type="mittal.events.DigitalClockEvent")]
/**
* Dispatched when the clock stops.
*
* @eventType mittal.events.DigitalClockEvent.CLOCK_STOP
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[Event(name="clockStop", type="mittal.events.DigitalClockEvent")]
/**
* Dispatched when the timer tick event occurs.
*
* @eventType mittal.events.DigitalClockEvent.CLOCK_TICK
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[Event(name="secondOver", type="mittal.events.DigitalClockEvent")]
/**
* Dispatched every minute.
*
* @eventType mittal.events.DigitalClockEvent.MINUTE_OVER
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[Event(name="minuteOver", type="mittal.events.DigitalClockEvent")]
/**
* Dispatched every hour.
*
* @eventType mittal.events.DigitalClockEvent.HOUR_OVER
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[Event(name="hourOver", type="mittal.events.DigitalClockEvent")]
/**
* Dispatched every Day.
*
* @eventType mittal.events.DigitalClockEvent.DAY_OVER
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[Event(name="dayOver", type="mittal.events.DigitalClockEvent")]
public class DigitalClock extends Label
{
public static const YEAR:String = "fullYear";
public static const MONTH:String = "month";
public static const WEEK:String = "week";
public static const DAY_OF_MONTH:String = "date";
public static const HOURS:String = "hours";
public static const MINUTES:String = "minutes";
public static const SECONDS:String = "seconds";
public static const MILLISECONDS:String = "milliseconds";
/**
* Constructor.
*
* @langversion 3.0
* @playerversion Flash 10
* @productversion Flex 4
*/
public function DigitalClock()
{
super();
_timerControl = new Timer(1000,0);
_dateControl = new Date();
addTimerControlEvents();
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
private var mouseIsOver:Boolean;
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// Timer Control
//----------------------------------
private var _timerControl:Timer;
/**
* The Timer class to update time.
* This is read only property.
*
*/
public function get timerControl():Timer
{
return (_timerControl != null)? _timerControl: new Timer(1000,0);
}
//----------------------------------
// Date Control
//----------------------------------
private var _dateControl:Date;
/**
* This control is used to set the time of clock.
* This is read only property.
*
*/
public function get dateControl():Date
{
return (_dateControl != null)? _dateControl: new Date();
}
//----------------------------------
// Clock Time Properties.
//----------------------------------
private var _time:String;
/**
* This control is used to set the time for the clock.
*
*/
[Bindable(event="timeChanged")]
public function get time():String
{
return _time;
}
public function set time(value:String):void
{
if(_time == value)
return;
_time = value;
dispatchEvent( new Event( "timeChanged" ) );
}
private var _hours:uint;
/**
* This control is used to set the hours for the clock.
*
*/
[Bindable(event="hoursChanged")]
public function get hours():uint
{
return _hours;
}
public function set hours(value:uint):void
{
//We dont want the control to be returned even for same value.
if (_hours == value)
return;
_hours = value;
isClockReset = true;
dispatchEvent( new Event( "hoursChanged" ) );
}
private var _minutes:uint;
/**
* This control is used to set the minutes for the clock.
*
*/
[Bindable(event="minutesChanged")]
public function get minutes():uint
{
return _minutes;
}
public function set minutes(value:uint):void
{
if (_minutes == value)
return;
_minutes = value;
isClockReset = true;
dispatchEvent( new Event( "minutesChanged" ) );
}
private var _seconds:uint;
/**
* This control is used to set the hours for the clock.
*
*/
[Bindable(event="secondsChanged")]
public function get seconds():uint
{
return _seconds;
}
public function set seconds(value:uint):void
{
if (_seconds == value)
return;
_seconds = value;
isClockReset = true;
dispatchEvent( new Event( "secondsChanged" ) );
}
//----------------------------------
// Event Suppress Control Properties
//----------------------------------
private var secsSuppressed:Boolean = false;
private var minsSuppressed:Boolean = false;
private var hoursSuppressed:Boolean = false;
private var daysSuppressed:Boolean = false;
[Inspectable(enumeration="secs,mins,hours,secs-Mins,mins-Hours,secs-Hours,secs-Mins-Hours")]
public function set suppressEvents(value:String):void
{
var params:Array = value.split("-");
suppressTimeEvents(params);
}
/**
* @private
*/
private function suppressTimeEvents(timeArray:Array):void
{
var index:int = 0;
var timeFragment:String;
for (index = 0; index<timeArray.length; index++)
{
timeFragment = String (timeArray[index]).toLowerCase();
this[timeFragment + 'Suppressed'] = true;
}
}
private var _isClockReset:Boolean = false;
/**
* Contains <code>true</code> if the clock is reset.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get isClockReset():Boolean
{
return _isClockReset;
}
public function set isClockReset(value:Boolean):void
{
if(_isClockReset == value)
return;
_isClockReset = value;
this.invalidateProperties();
}
protected function initializeClockTimeVariables():void
{
hours = dateControl.hours;
minutes = dateControl.minutes;
seconds = dateControl.seconds;
}
/**
* @private
*/
private function addTimerControlEvents():void
{
timerControl.addEventListener(TimerEvent.TIMER, onTimerTickEventHandler);
timerControl.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerCompleteEventHandler);
initializeClockTimeVariables();
timerControl.start();
}
/**
* @private
*/
private function removeTimerControlEvents():void
{
timerControl.removeEventListener(TimerEvent.TIMER, onTimerTickEventHandler);
timerControl.removeEventListener(TimerEvent.TIMER_COMPLETE, onTimerCompleteEventHandler);
}
protected function onTimerTickEventHandler(event:TimerEvent):void
{
_dateControl = dateAdd("seconds",1,dateControl);
updateTime();
}
private function updateTime():void
{
seconds = dateControl.seconds;
minutes = dateControl.minutes;
hours = dateControl.hours;
time = dateControl.hours + ":" + dateControl.minutes + ":" + dateControl.seconds;
//Logic to dispatch time related events.
if(!secsSuppressed)
this.dispatchEvent( new DigitalClockEvent(DigitalClockEvent.SECOND_OVER));
if((dateControl.seconds)%60==0 && !minsSuppressed)
{
this.dispatchEvent( new DigitalClockEvent(DigitalClockEvent.MINUTE_OVER));
//Minute has got changed so check whether an hour is over or not?
if((dateControl.minutes)%60==0 && !hoursSuppressed)
{
this.dispatchEvent( new DigitalClockEvent(DigitalClockEvent.HOUR_OVER));
//Hour has got changed so check whether a day is over or not?
if((dateControl.hours)%24==0 && !daysSuppressed)
{
this.dispatchEvent( new DigitalClockEvent(DigitalClockEvent.DAY_OVER));
}
}
}
}
protected function onTimerCompleteEventHandler(event:TimerEvent):void
{
//Need to work.
}
/**
* Starts the Clock Ticking
*
*/
public function startClock():void
{
timerControl.start();
}
/**
* Stops the Clock Ticking
*
*
*/
public function stopClock():void
{
timerControl.stop();
}
/**
* If user tries to assign values to hour/minute/seconds then reset the Clock Time to the entered value.
* We can set hours, minutes and seconds individually as well
* as together using this function.
*
*/
public function resetClock(hoursValue:*, minutesValue:*, secondsValue:*):void
{
stopClock();
dateControl.setHours(hoursValue);
dateControl.setMinutes(minutesValue);
dateControl.setSeconds(secondsValue);
startClock();
}
/**
* Destroy the Clock. Remove all event listeners and other clean-up work.
*
*
*/
public function destroyClock():void
{
removeTimerControlEvents();
}
/**
* Adds the specified number of "date parts" to a date, e.g. 6 days
*
* @param datePart The part of the date that will be added
* @param number The total number of "dateParts" to add to the date
* @param date The date on which to add
*
* @return The new date
*/
public function dateAdd( datePart:String, number:Number, date:Date = null):Date {
var _returnDate:Date = (date)? (date) : new Date();
switch ( datePart )
{
case YEAR:
case MONTH:
case DAY_OF_MONTH:
case HOURS:
case MINUTES:
case SECONDS:
case MILLISECONDS:
_returnDate[ datePart ] += number;
break;
case WEEK:
_returnDate[ DAY_OF_MONTH ] += number * 7;
break;
default:
/* Unknown date part, do nothing. */
break;
}
return _returnDate;
}
/**
* @private
*/
private function getUSClockTime(hrs:uint, mins:uint, secs:int):String {
// Returns the time in "Hrs:Mins:Sec AM/PM " format.
var modifier:String = "PM";
var minLabel:String = doubleDigitFormat(mins);
var secLabel:String = doubleDigitFormat(secs);
if(hrs > 12) {
hrs = hrs-12;
} else if(hrs == 0) {
modifier = "AM";
hrs = 12;
} else if(hrs < 12) {
modifier = "AM";
}
return (doubleDigitFormat(hrs) + ":" + minLabel + ":" + secLabel + modifier);
}
/**
* @private
*/
private function doubleDigitFormat(num:uint):String {
/*
Returns the String value in double digit format. If num is less than 10 it has a leading zero else
the num is converted to String and returned
*/
if(num < 10) {
return ("0" + num);
}
return String(num);
}
/**
* @private
*/
private function getTimeValue(value:*):uint
{
if(value is String)
return parseInt(value);
else if (value is uint)
return value;
return 0;
}
/**
* @private
*/
override protected function commitProperties():void
{
super.commitProperties();
//Clock value can be set multiple times.
if(isClockReset)
{
isClockReset = false;
resetClock(_hours,_minutes,_seconds);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
xmlns:components="mittal.components.*">
<fx:Script>
<![CDATA[
import mittal.events.DigitalClockEvent;
import mx.controls.Alert;
protected function clock_minuteOverHandler(event:DigitalClockEvent):void
{
Alert.show("Minute Over");
}
protected function clock_hourOverHandler(event:DigitalClockEvent):void
{
Alert.show("hour Over");
}
protected function clock_secondOverHandler(event:DigitalClockEvent):void
{
Alert.show("Second Over");
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout gap="10" verticalAlign="middle"/>
</s:layout>
<components:DigitalClock id="clock" width="400" height="50"
secondOver="clock_secondOverHandler(event)"
minuteOver="clock_minuteOverHandler(event)"
hourOver="clock_hourOverHandler(event)"
suppressEvents="secs-Mins"
/>
<s:Group>
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Label text="{clock.time}" fontSize="40"/>
</s:Group>
<s:Group>
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Button label="Start Clock" click="{clock.startClock();}"/>
<s:Button label="Stop Clock" click="{clock.stopClock();}"/>
<s:Button label="Hour" click="{clock.hours = 10;}"/>
<s:Button label="Min" click="{clock.minutes = 59;}"/>
<s:Button label="sec" click="{clock.enableSuppressedEvents = 'secs-Mins';}"/>
<s:Button label="Time" click="{clock.resetClock(12,12,12);}"/>
</s:Group>
</s:Application>
+