Timer.phpg
6eaf871a
 #!/usr/local/bin/php
 <?php
 # Simple Countdown or Countup Timer for PHP-GTK
 #
6bd25834
 # Last modified Feb. 13, 2018.
 # 
 # First released March 31, 2017.
6eaf871a
 #
 #------------------------------------------------------------------------------
 #
 #
 # All arguments are optional.  If no arguments are provided, the timer will
 # display a 5 minute countdown by default.
 #
 #
6bd25834
 # Arg 1: "title"
 # The title you want the timer window to have.
 #
 # Arg 2: "note"
 # A note you want shown near the top of the timer window.
 #
 # Arg 3: "icon_fillepath"
 # A fillepath (full, absolute filepath) to your desired icon for the
 # timer window's title bar.
6eaf871a
 #
 #
6bd25834
 # Arg 4:  "count_up_or_down"
6eaf871a
 # Possible settings: "up" or "down"
 #
 #
6bd25834
 # Arg 5: "dest_datetime"
6eaf871a
 #
 # To make the timer count down (or up) all the seconds until a particular date/time,
 # set this to any date/time text that PHP's strtotime() function can understand.
 #
 # This is impressively flexible - see the below links for examples.
 #
 # http://php.net/manual/en/datetime.formats.relative.php
 # http://php.net/manual/en/datetime.formats.time.php
 # http://php.net/manual/en/datetime.formats.date.php
 #
6bd25834
 # If you set Arg 5, don't set Args 8 thru 13, since they'll be ignored.
6eaf871a
 #
 # 
6bd25834
 # Arg 6: "dest_datetime_format"
6eaf871a
 #
 # If you don't set this, dest_datetime will be displayed in the timer window
 # in this format by default: "Fri, 31 Mar 2017 14:56:04 -0400"
 #
6bd25834
 # Arg 6 lets you choose your own format.  See this link for more info:
6eaf871a
 #
 # http://php.net/manual/en/function.date.php
 #
 #
6bd25834
 # Arg 7: "shell_command_to_exec_when_timer_done"
6eaf871a
 # A shell command you want executed after the timer is done with its countdown (or countup).
1a3ba282
 #
6eaf871a
 #
6bd25834
 # Args 8, 9, 10: "total_hours", "total_mins", "total_secs"
6eaf871a
 # The total amount of time you want the timer to run.
 #
6bd25834
 # Ignored if Arg 5 ("dest_datetime") is present.
6eaf871a
 #
 #
6bd25834
 # Args 11, 12, 13: "start_hours", "start_mins", "start_secs"
6eaf871a
 # Set one or more of these if you want to make the timer skip ahead to a later time in
 # the countdown (or countup).
 #
6bd25834
 # Ignored if Arg 5 ("dest_datetime") is present.
6eaf871a
 #
 #
6bd25834
 # Arg 14: "should_show_start_and_end_times"
6eaf871a
 # Set to "y" or "yes" to make the timer definitely display the text "Timer started:"
 # and "Timer ended:".
 #
 # Set to anything else to hide that text.
 #
 # If not set, the value of the constant "Default_for_should_show_start_and_end_times"
 # is used instead.
 #
 #
 #------------------------------------------------------------------------------
 #
 #
 # Under the GNU Affero General Public License v3.0.
 #
6bd25834
 # Copyright (C) 2017/2018  Apollia
6eaf871a
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
 #    published by the Free Software Foundation, either version 3 of the
 #    License, or (at your option) any later version.
 #
 #    This program is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU Affero General Public License for more details.
 #
 #    You should have received a copy of the GNU Affero General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #
 # Contact info:     http://astroblahhh.com/contact-apollia.shtml
 #
 #-----
 
 
6bd25834
 $scripthome=dirname(__FILE__);
 $Fillepath____Default_Icon="$scripthome/Icons/clock-icon.png";
6eaf871a
 
6bd25834
 			
 			
6eaf871a
 $Default_Total_Hours=0;
 $Default_Total_Mins=5;
 $Default_Total_Secs=0;
 
 $orig_working_dir=getcwd();
 define ("Orig_Working_Dir", $orig_working_dir);
 
 define ("Default_for_should_show_start_and_end_times", true);
 
 
 
 
 trait Magic_Getter
 {
 	public function __get($property)
 	{
 		if (property_exists($this, $property) )
 		{
 			return $this->$property;
 		}
 		else
 		{
 			$class=get_class($this);
 			echo "$class doesn't have a $property property!  Aborting.";
 			exit;
 		}	
 	}
 }
 
 
 
 
 class Prototype___Mr_Cliargs
 {
 	protected $script_filename;
 	protected $args;
 	protected $arg_count;
 	
 
 
 	public function Get_Cliargs ()
 	{
 		global $argv;
 		
 		$args=$argv;
 		$script_filename=array_shift($args);
 		
 		$arg_count=count($args);
 
 		$this->arg_count=$arg_count;
 		$this->script_filename=$script_filename;
 		$this->args=$args;
 
 	}
 	
 	
 	
 	public function Maybe_Get_Arg( $num )
 	{
 		$args=$this->args;
 		
 		if (isset ($args[$num] ) )
 		{
 			return $args[$num];
 		}
 		else
 		{
 			return null;
 		}
 	}
 	
 	
 	
 	public function Get_Arg( $num )
 	{
 		$args=$this->args;
 		
 		if (isset ($args[$num] ) )
 		{
 			return $args[$num];
 		}
 		else
 		{
 			$display_num=$num+1;
 			echo "Aborting: No arg $display_num found!";
 			br();
 			exit;
 		}
 	}
 	
 	
 	
 	public function Get_Count()
 	{
 		return $this->$arg_count;
 	}
 }
 
 
 
 
 class Prototype___Mr_Raw_Input
 {
6bd25834
 	protected $args_to_get=array("title", "note", "icon_fillepath", "count_up_or_down", "dest_datetime", "dest_datetime_format", "shell_command_to_exec_when_timer_done", "total_hours", "total_mins", "total_secs", "start_hours", "start_mins", "start_secs", "should_show_start_and_end_times" );
6eaf871a
 	
 	protected $raw_input=array();
 	
 
 	use Magic_Getter;
 	
 	
 	
 	public function Fetch_Raw_Input()
 	{
 		global $Mr_Cliargs;
 		
 		$args_to_get=$this->args_to_get;
 		
 		$argnum=0;
 		foreach ($args_to_get as $arg)
 		{
 			
 			$this->raw_input[$arg]= $Mr_Cliargs->Maybe_Get_Arg($argnum);
 			$argnum++;
 		}
 		print_r($this->raw_input);
 		
 	}
 }
 
 
 
 
 class Prototype___Mr_Standardized_Input
 {
 
6bd25834
 	protected $raw_input;
 	protected $standardized_input;
6eaf871a
 	
 	use Magic_Getter;
 
 
 
 	public function __construct()
 	{
 		global $Mr_Raw_Input;
 		
6bd25834
 		$this->raw_input=$Mr_Raw_Input->raw_input;
6eaf871a
 		
 	}
 
 	
 	
 	public function Standardize_Raw_Input()
 	{
6bd25834
 		$raw=$this->raw_input;
6eaf871a
 		
6bd25834
 		#echo "Raw title:";
 		#echo $raw["title"];
6eaf871a
 		
6bd25834
 		#--------------------------------------
 		# title
 		if ( ! $raw["title"] )
 		{	
 			$this->standardized_input["title"]="Timer";
 		}
 		else
 		{	
 			$this->standardized_input["title"]=$raw["title"];
 		}
6eaf871a
 		
 		
6bd25834
 		#--------------------------------------
 		# note
 		
 		$this->standardized_input["note"]=$raw["note"];
 		
 
 		#--------------------------------------
 		# icon_fillepath
 		
 	#	$this->standardized_input["icon_fillepath"]=$raw["icon_fillepath"];
 		if ( ! $raw["icon_fillepath" ] )
6eaf871a
 		{
6bd25834
 			global $Fillepath____Default_Icon;
 			$this->standardized_input["icon_fillepath"]=$Fillepath____Default_Icon;
6eaf871a
 		}
6bd25834
 		else
6eaf871a
 		{
6bd25834
 			$this->standardized_input["icon_fillepath"]=$raw["icon_fillepath"];
6eaf871a
 		}
6bd25834
 		
 		#--------------------------------------
 		# count_up_or_down
 		
 		
 		if ( $raw["count_up_or_down"] == "up" || $raw["count_up_or_down"] == "down")
6eaf871a
 		{
6bd25834
 			$this->standardized_input["count_up_or_down"]=$raw["count_up_or_down"];
6eaf871a
 		}
6bd25834
 	
 		else if ( $raw["count_up_or_down"] != "up" && $raw["count_up_or_down"] != "down")
6eaf871a
 		{
6bd25834
 			$this->standardized_input["count_up_or_down"]="down";
6eaf871a
 		}
6bd25834
 		
 		
 		#--------------------------------------
 		# dest_datetime
 		
 		if ( $raw["dest_datetime"] )
6eaf871a
 		{
6bd25834
 			$dest_unixtime=strtotime( $raw["dest_datetime"] );
6eaf871a
 			#echo "dest_unixtime: $dest_unixtime";
 			if ($dest_unixtime==false)
 			{	
6bd25834
 				$this->standardized_input["dest_datetime"]="";
6eaf871a
 			}
 			else
 			{
6bd25834
 				$this->standardized_input["dest_datetime"]=$dest_unixtime;
6eaf871a
 			}
 		}
6bd25834
 		else
 		{
 			$this->standardized_input["dest_datetime"]="";
 		}
6eaf871a
 		
6bd25834
 		
 		#--------------------------------------
 		# dest_datetime_format
 		
 		if ( ! $raw["dest_datetime_format"] )
6eaf871a
 		{
6bd25834
 			$this->standardized_input["dest_datetime_format"] = "r";
 		}
 
 		
 		#--------------------------------------
 		# shell_command_to_exec_when_timer_done
 		
 		$this->standardized_input["shell_command_to_exec_when_timer_done"]=$raw["shell_command_to_exec_when_timer_done"];
 		
 		
 		#--------------------------------------
 		# total_hours
 		
 		$this->standardized_input["total_hours"]=$raw["total_hours"];
 		
 		#--------------------------------------
 		# total_mins
 		
 		$this->standardized_input["total_mins"]=$raw["total_mins"];
 		
 		#--------------------------------------
 		# total_secs
 		
 		$this->standardized_input["total_secs"]=$raw["total_secs"];
 		
 		#--------------------------------------
 		# start_hours
 		
 		$this->standardized_input["start_hours"]=$raw["start_hours"];
 		
 		#--------------------------------------
 		# start_mins
 		
 		$this->standardized_input["start_mins"]=$raw["start_mins"];
 		
 		#--------------------------------------
 		# start_secs
 		
 		$this->standardized_input["start_secs"]=$raw["start_secs"];
 		
 		
 		#--------------------------------------
 		# should_show_start_and_end_times
 		
 		$should_show_start_and_end_times = $raw["should_show_start_and_end_times"];
 		
 		
 		if ($should_show_start_and_end_times == "y" || $should_show_start_and_end_times == "yes" )
 		{
 			$this->standardized_input["should_show_start_and_end_times"] = "y";
 		}
 		else if ($should_show_start_and_end_times )
 		{
 			$this->standardized_input["should_show_start_and_end_times"]=false;
 		}
 		else if (!$should_show_start_and_end_times)
 		{
 			$this->standardized_input["should_show_start_and_end_times"]=Default_for_should_show_start_and_end_times;
6eaf871a
 		}
 	}
 }
 
 
 
 
 class Prototype___Mr_Valichecker
 {
 
 		
 	
 	public function Do_Valicheck_of_Input()
 	{
 		global $Mr_Standardized_Input;
 		
6bd25834
 		$input = $Mr_Standardized_Input->standardized_input;
6eaf871a
 		
 		$this->Valicheck_Arg____Must_Be_Integer_or_Empty($input["total_hours"], "total hours");
 		$this->Valicheck_Arg____Must_Be_Integer_or_Empty($input["total_mins"], "total mins");
 		$this->Valicheck_Arg____Must_Be_Integer_or_Empty($input["total_secs"], "total secs");
 		
 		$this->Valicheck_Arg____Must_Be_Integer_or_Empty($input["start_hours"], "start hours");
 		$this->Valicheck_Arg____Must_Be_Integer_or_Empty($input["start_mins"], "start mins");
 		$this->Valicheck_Arg____Must_Be_Integer_or_Empty($input["start_secs"], "start secs");
 		
 		$this->Valicheck_Arg____count_up_or_down( $input["count_up_or_down"]);
 		$this->Valicheck_Arg____dest_datetime( $input["dest_datetime"] );
 		return true;
 	}
 	
 	
 	
 	protected function Valicheck_Arg____dest_datetime( $arg)
 	{
 		if (! $arg)
 		{
 			return true;
 		}
 		/*
 		$now_unixtime=time();
 		
 		if  ( ($arg - $now_unixtime ) < 0 )
 		{
 			$abort_message="Aborting: dest_datetime must not be in the past!";
 			
 			echo "\n\n$abort_message\n";
 			Alert($abort_message);
 			exit(2);
 		}
 		* */
 	}
 	
 	
 	
 	protected function Valicheck_Arg____count_up_or_down( $arg )
 	{
 		if ( $arg != "down" && $arg != "up" )
 		{
 			echo "Aborting because count_up_or_down must be either up or down!";
 			exit;
 		}
 	}
 	
 	
 	
 	protected function Valicheck_Arg____Must_Be_Integer_or_Empty( $arg, $what_it_is )
 	{
 		if ( !$arg )
 		{	return true;
 		}
 		if (is_int( (int) $arg) )
 		{
 			return true;
 		}
 		echo "Aborting: $what_it_is must be an integer, but it's $arg!";
 		exit;
 	}
 	
 }
 
 
 
 function Calculate_Seconds_in_Hours_Mins_Secs($hours, $mins, $secs)
 {
 	$hoursecs=60*60*$hours;
 	$minsecs=60*$mins;
 
 	return $hoursecs+$minsecs+$secs; 
 }
 
 
 
 function Alert($msg)
 {
     $Dialog = new GtkDialog('Alert', null, Gtk::DIALOG_MODAL);
     $Dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
     
     $vbox = $Dialog->vbox;
     $vbox->pack_start($hbox = new GtkHBox());
     
     $stock = GtkImage::new_from_stock(Gtk::STOCK_DIALOG_WARNING,
         Gtk::ICON_SIZE_DIALOG);
         
     $hbox->pack_start($stock, 0, 0);
     $hbox->pack_start(new GtkLabel($msg));
     
     $Dialog->add_button(Gtk::STOCK_OK, Gtk::RESPONSE_OK);
     $Dialog->set_has_separator(false);
     $Dialog->show_all();
     $Dialog->run();
     $Dialog->destroy();
 }
 
 
 
 
 
 
 
 function Start_Timer( $Args_for_Timer )
 {
 	global $Total_Time;
 	
     $Mr_Timer = new Prototype___Mr_Timer;
     
     $Mr_Timer->Initialize( $Args_for_Timer );
     
     $Mr_Timer->Start();   
 }
 
 
 
 class Prototype___Mr_Timer
 {
     protected $Timer_Text;
     protected $Timer_Dialog;
     
     protected $DateTime_At_Start;
     protected $DateTime_At_End;
     
     protected $Start_Label;
     protected $End_Label;
     
     protected $Pause_Button;
     protected $Resume_Button;
     
     protected $Pause_Label;
     protected $Note_Label;
     
     protected $total_time;
     protected $total_time_text;
     
     protected $time_left;
     
     protected $timeout_ID=null;
     
     protected $start_time;
 
 	protected $counting_down;
 	protected $counting_up;
 	protected $count_up_or_down;
 
 	protected $timer_done=false;
 	protected $past_dest_datetime;
 	protected $Past_DateTime;
 	
 	protected $should_show_start_and_end_times;
 	
 	
 	
6bd25834
 	//~ public function On_Status_Icon_Click()
 	//~ {
 		//~ echo "yay";
 		//~ Alert("test");
 		//~ $Timer_Dialog=$this->Timer_Dialog;
 		//~ 
 		//~ if ($Timer_Dialog->is_visible())
 		//~ {	
 			//~ $Timer_Dialog->hide_all();
 		//~ }
 		//~ else
 		//~ {	$Timer_Dialog->show_all();
 		//~ }
 	//~ }
6eaf871a
 	public function Start()
 	{
 		#if ($this->counting_up)
 		#{
 			$this->Update_Timer();
 			$this->Start_Timer();
 		#}
 		#else
 		#{
 		#	$this->Update_Timer();
 		#	$this->Start_Timer();
 		#}
 	}
 	
 	
 	
     public function Initialize( $Args_for_Timer)
     {   
 		foreach ($Args_for_Timer as $key => $value)
 		{
 			#echo "Arg: $key  $value\n";
 			${$key}=$value;
 		}
 		
 		
 		if ($past_dest_datetime)
 		{
 			$count_up_or_down="up";
 		}
 		
 		$this->count_up_or_down=$count_up_or_down;
 		$this->shell_command_to_exec_when_timer_done=$shell_command_to_exec_when_timer_done;
 		$this->past_dest_datetime=$past_dest_datetime;
 		$this->should_show_start_and_end_times=$should_show_start_and_end_times;
 		
 
 		
 		if ( $count_up_or_down == "up" )
 		{
 			$this->counting_down=false;
 			$this->counting_up=true;
 			$this->Set_Time_Left_to_($Total_Time-$Start_Time);
 		}
 		else
 		{
 			$this->counting_down=true;
 			$this->counting_up=false;
 			$this->Set_Time_Left_to_($Total_Time);
 			$this->Set_Time_Left_to_($Total_Time-$Start_Time);
 		}
 		
 		$this->Set_Total_Time_to_($Total_Time);
 		
6bd25834
 		
 		
 		
 		$Timer_Dialog = new GtkDialog("$Title", null, Gtk::DIALOG_MODAL);
        
        
        # 15:46:46 02/13/20185.  Couldn't get the status icon to work at all.
        # 
        # http://www.devshed.com/c/a/php/building-your-own-system-tray-application-using-php-gtk/
        
        //~ $statusicon = new GtkStatusIcon();
 		//~ global $Fillepath____Default_Icon;
 		//~ $statusicon->set_from_stock(Gtk::STOCK_FILE);
 		//~ #$statusicon->set_from_file("$Fillepath____Default_Icon");
 		//~ $statusicon->set_visible(true);
 		//~ $statusicon->set_blinking(true);
 		//~ $statusicon->connect('activate', array(&$this, 'On_Status_Icon_Click') );
 
 		#Alert("test");
 		if ( $Icon_Fillepath )
 		{
 			$pixbuf=GdkPixbuf::new_from_file("$Icon_Fillepath");
6eaf871a
        
6bd25834
 			$Timer_Dialog->set_icon($pixbuf);
 		}
        
 		
         $Accel_Group=new GtkAccelGroup();
         $Timer_Dialog->add_accel_group($Accel_Group);
         
         
6eaf871a
 		#$Timer_Dialog->set_size_request(400, 140);
        
         $vbox = $Timer_Dialog->vbox;
         
6bd25834
         
eb24a8bb
         
        # $this->Timer_Text = new GtkLabel();
         
6bd25834
         if ( ! $dest_datetime )
         {
 			$Quit_Button=GtkButton::new_from_stock(Gtk::STOCK_QUIT);
 		
 			#$Quit_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_Q, Gdk::CONTROL_MASK, 0 );
 			$vbox->pack_start($Quit_Button);
 			$Quit_Button->connect('clicked', array(&$this, "Quit_Timer") );
eb24a8bb
 			
 			#$Timer_Dialog->set_default($this->Timer_Text);
 			
 			#$this->Timer_Text->grab_focus();
6bd25834
 		}
 		
 		
6eaf871a
         $this->Countdown_or_Up_Label = new GtkLabel();
         $this->Countdown_or_Up_Label->modify_font(new PangoFontDescription("Sans 12"));
         
      
 		$this->Pause_Label = new GtkLabel();
         $this->Pause_Label->modify_font(new PangoFontDescription("Sans 12"));
         
         
         $this->Note_Label = new GtkLabel();
         $this->Note_Label->modify_font(new PangoFontDescription("Sans 15"));
         $this->Note_Label->set_text("$Note");
         
6bd25834
         echo "TITLE: $Title";
6eaf871a
         $total_time_seconds = $this->total_time;
 
         $Now_DateTime=new DateTime("now");
 		$End_DateTime=new DateTime("now");
 		$End_DateTime->add(DateInterval::createFromDateString("$total_time_seconds seconds") );
 				
 		$Interval=$End_DateTime->diff($Now_DateTime, true);
 		
 		$format=$this->Get_Date_Format_But_Omit_Larger_Units_If_Possible($Interval);
 		$total_time_text=$Interval->format($format);
 			
 		$this->total_time_text=$total_time_text;
 		
 		
 		if ($this->counting_down )
 		{
 			$label = "Counting down ";
 		}
 		else
 		{
 			$label = "Counting up ";
 		}
 			
 		if ($dest_datetime)
 		{
 			
 			$formatted_dest_datetime=date( $dest_datetime_format, $dest_datetime );
 			
 			if ($past_dest_datetime)
 			{
 				$label="Time since $formatted_dest_datetime:";
 			}
 			else
 			{
 				$label .= "$total_time_text to $formatted_dest_datetime";
 			}
 		}
 		else
 		{
 			if ($this->counting_down )
 			{
 				$label .= "from $total_time_text";
 			}
 			else
 			{
 				$label .= "to $total_time_text";
 			}
 		}
 		
 		$countdown_or_up_label_text=$label;
        
 		$this->countdown_or_up_label_text=$countdown_or_up_label_text;
         
         $this->Countdown_or_Up_Label->set_text("$countdown_or_up_label_text");
         
         
         $vbox->pack_start($this->Note_Label);
         
dee99819
         $this->DateTime_At_Start=new DateTime("now");
 	    
6eaf871a
         if ( $this->should_show_start_and_end_times )
         {
 
 			$this->Start_Label = new GtkLabel();
 			$vbox->pack_start($this->Start_Label);
 			
dee99819
 			
6eaf871a
 			
 			$label="Timer Started: ";
 			$label .= $this->DateTime_At_Start->format("r");
 			
 			$this->Start_Label->set_text( $label );
 		}
         
         echo "\n\nStarted Timer: ";
         echo $this->DateTime_At_Start->format("r");
        # echo "\n";
         
         echo "\n\nTimer Note: $Note";
         
         $vbox->pack_start($this->Countdown_or_Up_Label);
         
         
eb24a8bb
 		$this->Timer_Text = new GtkLabel();
6eaf871a
         $this->Timer_Text->modify_font(new PangoFontDescription("Sans 24"));
         
         if ($this->counting_down)
         {
 			$timer_text_label="$total_time_text";
 
         }
         else
         {	
 			if ($past_dest_datetime)
 			{
 
 				$Past_DateTime=new DateTime();
 				$Past_DateTime->setTimestamp($dest_datetime);
 				
 				$Now_DateTime=new DateTime();
 				
 				$Time_Since=$Past_DateTime->diff($Now_DateTime);
 				
 				$format=$this->Get_Date_Format_But_Omit_Larger_Units_If_Possible($Time_Since);
 
 				$timer_text_label=$Time_Since->format("$format");
 				
 				$this->Past_DateTime=$Past_DateTime;
 				
 			}
 			else
 			{
 
 				if (strlen($total_time_text)>5 )
 				{
 					$timer_text_label="00:00:00";
 					
 				}
 				else
 				{
 					$timer_text_label="00:00";
 				}
 			}
 		}
         
         
         $this->Timer_Text->set_text($timer_text_label);
         
         $vbox->pack_start($this->Timer_Text);
         
eb24a8bb
         
         #$Timer_Dialog->set_default($this->Timer_Text);
 			
 		#$this->Timer_Text->grab_focus();
 			
6eaf871a
         $vbox->pack_start($this->Pause_Label);
         
         
         if ( $this->should_show_start_and_end_times )
         {
 			$this->End_Label = new GtkLabel();
 			$vbox->pack_start($this->End_Label);
         }
         
eb24a8bb
 		$Blank_Button=new GtkButton(" ");
 		$vbox->pack_start($Blank_Button);
 		$Timer_Dialog->set_default($Blank_Button);
 		$Blank_Button->grab_focus();
6bd25834
         
6eaf871a
         if ( !$dest_datetime )
         {
 			$Pause_Button=new GtkButton("Pause");
 			$Resume_Button=new GtkButton("Resume");
         
6bd25834
 			$Pause_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_P, Gdk::CONTROL_MASK, 0 );
 			$Pause_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_P, 0, 0 );
 			$Pause_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_S, Gdk::CONTROL_MASK, 0 );
 			$Pause_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_S, 0, 0 );
 			$Resume_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_R, Gdk::CONTROL_MASK, 0 );
 			$Resume_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_R, 0, 0 );
 			
6eaf871a
 			$vbox->pack_start($Pause_Button);
 			$vbox->pack_start($Resume_Button);
         
 			$Pause_Button->connect('clicked', array(&$this, "Pause_Timer") );
eb24a8bb
 			$Timer_Dialog->set_default($Pause_Button);
 			$Pause_Button->grab_focus();
 			
6eaf871a
 			$Resume_Button->connect('clicked', array(&$this, "Resume_Timer") );
         }
6bd25834
         else
         {
 			$Quit_Button=GtkButton::new_from_stock(Gtk::STOCK_QUIT);
 	
 			$vbox->pack_start($Quit_Button);
 			$Quit_Button->connect('clicked', array(&$this, "Quit_Timer") );
eb24a8bb
 			
 			#$Timer_Dialog->set_default($this->Timer_Text);
 			
 			#$this->Timer_Text->grab_focus();
6bd25834
 		}
1a3ba282
 		
 		
eb24a8bb
 		
 		
 		
 		
6bd25834
 		$Quit_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_Q, Gdk::CONTROL_MASK, 0 );
1a3ba282
   #      $Quit_Button->add_accelerator('clicked', $Accel_Group, Gdk::KEY_Q, 0, 0 );
6eaf871a
         
6bd25834
 		
1a3ba282
 		$Timer_Dialog->connect('key-press-event', array (&$this, 'on_timer_window_keypress')); 
 		
eb24a8bb
 		
 		#$Quit_Button->set_sensitive(false);
 		
6eaf871a
         $Timer_Dialog->set_has_separator(false);
         $Timer_Dialog->show_all();
         
eb24a8bb
         #$Quit_Button->hide();
6eaf871a
         
         $this->Timer_Dialog = $Timer_Dialog;
 
         $Timer_Dialog->connect('delete-event',
             array( &$this, "Upon_Delete_Event"));
 
         $this->start_time = microtime(1);
     }
     
     
     
     protected function Note_End_Time()
     {
 		$this->DateTime_At_End=new DateTime("now");
 	}
 	
 	
 	
 	public function Set_End_Label()
 	{
 	
 		
         
         $label="Timer Ended: ";
         $label .= $this->DateTime_At_End->format("r");
         
         $this->End_Label->set_text( $label );
         
 	}
 	
 	
 	
 	public function Set_Total_Time_to_($seconds)
 	{
 		$this->total_time=$seconds;
 	}
 	
 	
 	
 	public function Set_Time_Left_to_($seconds)
 	{	$this->time_left=$seconds;
 	}
 	
 	
 	
 	public function Start_Timer()
 	{	
 		$count_up_or_down=$this->count_up_or_down;
 		
 		echo "\n\n\n"; echo "Starting Count$count_up_or_down Timer";
 		echo " - ";
 		echo $this->countdown_or_up_label_text;
 		
 		#$this->Show_Time_Left();
 		$this->Show_Time_Left_and_Time_Elapsed();
 		
 		$this->start_time = microtime(1);
 		$this->timeout_ID = Gtk::timeout_add(1000,
 			array(&$this, 'Update_Timer'));
 	}
 	
 	
 	
 	public function Resume_Timer()
 	{
 		if ( $this->timer_done)
 		{
 			return false;
 		}
 		if ($this->timeout_ID === null )
 		{
 			echo "\n\n"; echo "Resuming Timer"; echo "\n";
 			$this->Pause_Label->set_text('');
 
 			$this->Start_Timer();
 			
 		}
 	}
 	
 	
 	
 	protected function Perform_Pause()
 	{
 		
 		Gtk::timeout_remove($this->timeout_ID);
 		$this->timeout_ID=null;	
 		
 		echo "\n\n\n"; echo "Pausing Timer"; echo "\n";
 		
 		$this->Show_Time_Left_and_Time_Elapsed();
 	}
 	
 	
6bd25834
 	public function Quit_Timer()
 	{
 		exit(0);
 	}
6eaf871a
 	public function Pause_Timer()
 	{
 		if ( $this->timer_done)
 		{
 			return false;
 		}
 		if ($this->timeout_ID === null)
 		{
 			return true;
 		}
 		$this->Pause_Label->set_text('(paused)');
 		$this->Perform_Pause();
 	}
 	
 	
 	
 	protected function Show_Time_Left()
 	{
 		$timetext=$this->Assemble_Time_Text($this->time_left);
 	
 		echo "\nTime left: $timetext";
 	}
 	
 	
 	
 	protected function Show_Time_Elapsed()
 	{
 		$timetext=$this->Assemble_Time_Text( ( $this->total_time - $this->time_left ));
 		echo "\nTime elapsed: $timetext";
 	}
 	
 	
 	
 	protected function Show_Time_Left_and_Time_Elapsed()
 	{
 		$this->Show_Time_Left();
 		$this->Show_Time_Elapsed();	
 	}
 	
 	
 	
 	protected function Convert_to_Hours_Mins_Secs($time)
 	{
 		$hours= floor( $time / 60 / 60 );
 		$hoursecs=$hours*60*60;
         
 		$minutes=floor(($time-$hoursecs)/60);
 		$minutesecs=$minutes*60; 
         
 		$seconds=floor($time-$hoursecs-$minutesecs);
 			
 		return array($hours, $minutes, $seconds);
 	}
 	
 	
 	
 	protected function Get_Date_Format_But_Omit_Larger_Units_If_Possible($interval)
 	{
 		$format="";
 	
 		if ($interval->y)
 		{
 			$format .="%yy ";
 		}
 		if ($interval->m)
 		{	
 			$format .= "%mm ";
 		}
 		if ($interval->d)
 		{
 			$format .= "%dd ";
 		}
 		
 		$format.="%H:%I:%S";
 		
 		return $format;
 	}
 	protected function Assemble_Time_Text( $time )
 	{
 		list($hours, $minutes, $seconds) = $this->Convert_to_Hours_Mins_Secs($time);
 		
 		 # 04:56:13 03/30/2017.  Left-padding with zeros:
 		if ($hours!=0)
 		{
 			$hours=sprintf("%02d:", $hours);
 		}
 		else
 		{	$hours="";
 		}
 		$minutes=sprintf("%02d:", $minutes);
 		$seconds=sprintf("%02d", $seconds);
 
 		$timetext="$hours$minutes$seconds";
 		
 		return $timetext;
 
 	}
 	
 	
 	
     public function Update_Timer()
     {   
         $elapsed_time = microtime(1) - $this->start_time;
         $remaining_time = $this->total_time - $elapsed_time;
         
 	
         	
         if ( abs($remaining_time - $this->time_left ) > 1)
         {
 			$remaining_time=$this->time_left;
 			$elapsed_time=$this->total_time - $this->time_left;
 		}
 
 		
 		if ( $this->counting_down )
 		{	
 			$remaining_time=floor($remaining_time);
 
 			$Now_DateTime=new DateTime("now");
 			$End_DateTime=new DateTime("now");
 			$End_DateTime->add(DateInterval::createFromDateString("$remaining_time seconds") );
 			
 			$Interval=$End_DateTime->diff($Now_DateTime);
 			
 			$format=$this->Get_Date_Format_But_Omit_Larger_Units_If_Possible($Interval);
 			$timetext=$Interval->format($format);
 			
 
 			#$timetext=$this->Assemble_Time_Text($remaining_time);
 
 		}
 		else
 		{	
 			if ($this->past_dest_datetime)
 			{
 				$Past_DateTime=$this->Past_DateTime;
 				
 				$Time_Since=$Past_DateTime->diff( new DateTime('now') );
 				
 				$format=$this->Get_Date_Format_But_Omit_Larger_Units_If_Possible($Time_Since);
 				
 				$timetext=$Time_Since->format($format);
 				
 			}
 			else
 			{
 				$Now_DateTime=new DateTime("now");
 				$End_DateTime=new DateTime("now");
 				$elapsed_time=floor($elapsed_time);
 				$End_DateTime->add(DateInterval::createFromDateString("$elapsed_time seconds") );
 				
 				$Interval=$End_DateTime->diff($Now_DateTime);
 				
 				$format=$this->Get_Date_Format_But_Omit_Larger_Units_If_Possible($Interval);
 				$timetext=$Interval->format($format);
 			
 				#$timetext=$this->Assemble_Time_Text($elapsed_time);
 			}
 		}
 
 
 		$this->Timer_Text->set_text("$timetext");
 		 
 		
 		--$this->time_left;
 
         
         while (Gtk::events_pending()) {Gtk::main_iteration();}
 
         if ($remaining_time>0)
         {
             return true;
         } 
         else 
         {   
 			if ($this->past_dest_datetime)
 			{
 				# 22:55:48 03/30/2017.  If the dest_datetime is in the past, just keep going forever.
 				
 				return true;
 			}
             chdir(Orig_Working_Dir);
             #Alert(Orig_Working_Dir);
             
             $shell_command_to_exec_when_timer_done=$this->shell_command_to_exec_when_timer_done;
             
             
             
             if ($shell_command_to_exec_when_timer_done)
             {
 				echo "\n\n\nShell command about to be executed: $shell_command_to_exec_when_timer_done";
 				
 				exec("$shell_command_to_exec_when_timer_done", $output, $retcode);
 				
 				$output_string=implode("\n", $output);
 				echo "\n\n\nOutput:";
 				
 				echo "\n\n";
 				echo $output_string;
 				echo "\n\n";
             }
             
            # $this->Timer_Dialog->destroy();
             
             if ( $this->timeout_ID)
             {
 				Gtk::timeout_remove($this->timeout_ID);
 			}
 			
 			$this->Pause_Label->set_text("Timer Done");
 			
 			$this->Note_End_Time();
 			
 			if ( $this->should_show_start_and_end_times )
 			{
 				$this->Set_End_Label();
 			}
 			echo "\n\nTimer Done: ";
 			echo $this->DateTime_At_End->format("r");
 			echo "\n";
 			
 			$this->timer_done=true;
 			
 			#exit;
 			return false;
         }
     }
 
 
1a3ba282
 	public function on_timer_window_keypress($widget, $event)
 	{
 		
 		echo "\n\nA key was pressed while timer window was in focus!";
 		
 		echo "Key: ";
 		echo $event->keyval;
 		
 		if ($event->keyval==Gdk::KEY_Escape) 
 		{
 			echo "\n\nEscape was pressed!\n\n";
 		
 		
 			#!!!!
 			return true;
 				# 12:40:54 06/27/2020.  This blocks Esc from closing the timer window!
 				#
 				# 12:50:09 06/27/2020.  This page helped me figure out how to do this:
 				#
 				# https://www.kksou.com/php-gtk2/sample-codes/setup-interactive-search-in-GtkTreeView-for-PHP-GTK-v2.0-Part-1-non-OOP-version.php
 				
 		}
     
 	}
 	
6eaf871a
     // Called when user closes the timer.
     public function Upon_Delete_Event($widget, $event)
     {
 		echo "\n\n";
 		echo "Timer window closed!";
 		
1a3ba282
 		#echo "Widget: \n\n";
 		#print_r($widget);
 		
 		#echo "Event: \n\n";
 		#print_r($event);
 
     
     
6eaf871a
         $this->Timer_Dialog->destroy();
         
         if ($this->timeout_ID)
         {
 			Gtk::idle_remove($this->timeout_ID);
 		}
 		
 		exit;
     }
 }
 
 
 
 
 $Mr_Cliargs=new Prototype___Mr_Cliargs;
 $Mr_Cliargs->Get_Cliargs();
 
 $Mr_Raw_Input=new Prototype___Mr_Raw_Input;
 $Mr_Raw_Input->Fetch_Raw_Input();
 
 $Mr_Standardized_Input=new Prototype___Mr_Standardized_Input;
 $Mr_Standardized_Input->Standardize_Raw_Input();
 
 $Mr_Valichecker=new Prototype___Mr_Valichecker;
 $Mr_Valichecker->Do_Valicheck_of_Input();
 
 
 
6bd25834
 $input=$Mr_Standardized_Input->standardized_input;
 
 $Icon_Fillepath=$input["icon_fillepath"];
6eaf871a
 
 $count_up_or_down=$input["count_up_or_down"];
 $dest_datetime=$input["dest_datetime"];
 $dest_datetime_format=$input["dest_datetime_format"];
 
 $past_dest_datetime=false;
 $should_show_start_and_end_times=$input["should_show_start_and_end_times"];
 
 
 
 if ($dest_datetime)
 {
 	$now_unixtime=time();
 	
 	if ( $dest_datetime < $now_unixtime)
 	{
 		$past_dest_datetime=true;
 		#echo date("r");
 		$Start_Time=$now_unixtime-$dest_datetime;
 		$Total_Time=0;
 	}
 	else
 	{
 		$Total_Time=$dest_datetime-$now_unixtime;
 		$Start_Time=0;
 	}
 }
 else
 {
 	$Total_Time=Calculate_Seconds_in_Hours_Mins_Secs($input["total_hours"], $input["total_mins"], $input["total_secs"]);
 
 	if ($Total_Time==0)
 	{
 		$Total_Time=Calculate_Seconds_in_Hours_Mins_Secs($Default_Total_Hours, $Default_Total_Mins, $Default_Total_Secs);
 	}
 
 
 
 	if ( $input["start_hours"] || $input["start_mins"] || $input["start_secs"] )
 	{
 		$Start_Time=Calculate_Seconds_in_Hours_Mins_Secs($input["start_hours"], $input["start_mins"], $input["start_secs"]);
 		
 		if ($count_up_or_down=="down")
 		{
 			$Start_Time=$Total_Time-$Start_Time;
 		}
 	}
 	else
 	{
 		$Start_Time=0;
 	}
 
 
 
 
 	if ( $Start_Time > $Total_Time )
 	{
 		$abort_message="Aborting!  Start time ($Start_Time seconds) may not be larger than total time ($Total_Time seconds).";
 		
 		echo "\n\n$abort_message.\n";
 		
 		Alert("$abort_message");
 		exit(1);
 	}
 }
 
 
 $Note=$input["note"];
6bd25834
 $Title=$input["title"];
6eaf871a
 $shell_command_to_exec_when_timer_done=$input["shell_command_to_exec_when_timer_done"];
 
 
 
6bd25834
 $Names_of_Args_for_Timer=array("count_up_or_down", "Total_Time", "Start_Time", "Title", "Note", "shell_command_to_exec_when_timer_done", "dest_datetime", "dest_datetime_format", "past_dest_datetime", "should_show_start_and_end_times", "Icon_Fillepath");
6eaf871a
 
 
 foreach ($Names_of_Args_for_Timer as $arg)
 {
 	$Args_for_Timer["$arg"] = ${$arg};
 }
 
 
 Start_Timer( $Args_for_Timer );
 
 
efe319de
 Gtk::main();