18. Stopwatch

Creating a stopwatch was relatively easy with Prima's Widget::Time and the module Time::HiRes

mainwindow


use Prima qw(Buttons Application Widget::Time);
               
use Time::HiRes qw( gettimeofday ); # invoke the module Time::HiRes 

$app_width = 575;# to manipulate both the main window and the next widget
$mw = Prima::MainWindow->new(
	size  => [$app_width, 200],
	text  => 'Stopwatch',
	icon => Prima::Icon-> load('icon.png'),	
);


# Widget::Time is an inputline, which you can customize with inputline properties

$size_widget = 180;
$mw->insert( 'Widget::Time' =>

    origin  => [(($app_width/2) - ($size_widget/2)), 150],
    size    => [$size_widget, 39],	
	name => 'Time',
	time => [0,0,0],
	
	borderWidth => 0,
	alignment => ta::Center,	
	font   => { size => 26, },	

	cursorVisible => 0,
	readOnly => 1,
	enabled => 0,

);

# some global variables

$micro_sec;# for method gettimeofday() in this application it will be not used.

$current_time;
$start_time = 0;
$stop_time = 0;
$reset = 0;

$diff_current_start_time = 0;
$diff_current_stop_time = 0;

# subroutine, invoked by onTick (Timer object) and the start button
sub start_timer {
	    
	if ( (! $start_time) or ($reset) ) {
			
			($start_time, $micro_sec) = gettimeofday();
			$diff_current_start_time = 0;			
			$diff_current_stop_time  = 0;

			$stop_time = 0;
			$reset = 0;			
	}
	
	($current_time, $micro_sec) = gettimeofday();
			
	if($stop_time) {
# if the stop button (pause) was pressed (and $stop_time has been set), we need 
to calculate the pause interval. When starting the timer again, we correct 
the current time for the pause interval. If the stop button was pressed again, 
then the old pause interval is incremented with the new pause interval. Hence: +=
		$diff_current_stop_time += ($current_time - $stop_time);
		$stop_time = 0;
	}

	$diff_current_start_time = (($current_time - $diff_current_stop_time) - $start_time);

# convert to hour, minute and seconds	
	$hour = int( $diff_current_start_time / 3600 );
	$min = int( $diff_current_start_time / 60 );
	$sec = int( $diff_current_start_time % 60 );

	$mw->Time->time([$sec,$min,$hour]);
};	

$mw-> insert( Timer => 
	name => 'mcTimer',
	timeout => 1000,
	onTick  => sub {
		start_timer;
	},
);

# four buttons with some onClick actions

# default geometry settings
%mcPack = (pack => { fill => 'x', side => 'left', pad => 20 } );

$mw-> insert( 
	Button =>
			%mcPack,
			name => 'start_button',
			text => "Start",
			onClick => sub {
				start_timer;
				$mw->mcTimer->start;
				$mw->stop_button->enabled(1);
				$mw->reset_button->enabled(1);
			},
);

$mw-> insert( 
	Button =>
			%mcPack,
			name => 'stop_button',
			text => "Stop",
			onClick => sub {
				($stop_time, $micro_sec) = gettimeofday();
				$mw->mcTimer->stop,
			},
			enabled => 0,
);

$mw-> insert( 
	Button =>
			%mcPack,
			name => 'reset_button',
			text => "Reset",
			onClick => sub {
				$reset = 1;
				$mw->Time->time([0, 0, 0]); 
				$mw->mcTimer->stop,
				$mw->stop_button->enabled(0);
			},
			enabled => 0,
);

$mw-> insert( 
    Button =>
			%mcPack,
			text => "Exit",
			onClick => sub { 
				$::application-> close 
			},
);


run Prima;