#!/usr/cogent/bin/phgamma

/*
 * Timers are one of the easiest and most powerful features of Gamma.
 * There are three kinds of timers supported by Gamma:
 * 
 *       1) every	      - interval timer
 *       2) after	      - one_shot timer
 *       3) at		      - calendar (time_of_day) timer
 * 
 * This example demonstrates several uses of timers.
 * 
 * This file is best viewed with a tab width of 4.
 */

/*
 * Load Photon Widget convenience functions.
 */
require_lisp("PhotonWidgets");

/*
 * Load support for loading windows created in PhAB.
 */
require_lisp("PhabTemplate");

/*
 * Initiate the graphics session with the Photon window manager.
 */
PtInit(nil);

/*
 * Load and convert the window created in PhAB using PhabLoad function.
 * Set the first item returned (PtWindow) definition to be the variable
 * named win.
 */
win = car(PhabLoad("wgt/example09.wgtw"));

/*
 * Attach a callback to the 'add' buttons to call functions.
 */
PtAttachCallback(Add1,Pt_CB_ACTIVATE,#add_every_timer());
PtAttachCallback(Add2,Pt_CB_ACTIVATE,#add_after_timer());

/*
 * Attach a callback to the remove() function.
 */
PtAttachCallback(Remove1,Pt_CB_ACTIVATE,#remove_timer());

/*
 * function to update the label 'Label1' and increment the counter.
 */
counter := 0;

function increment ()
{
	Label1.text_string = string(++counter);
}

/*
 * This function adds a new timer which updates on a one second interval.
 * The time interval for an interval timer is specified in seconds, where
 * fractions of seconds use decimal notation.  For example, a 1/50th
 * of a second timer would be specified as 0.02.
 *
 * This function simply causes the 'increment' function defined above to
 * run on a 1-second interval, and then updates the timer list on the
 * screen.
 */
function add_every_timer ()
{
	every(1.0,#increment());
	update_timer_list();
}

/*
 * This function adds a new timer which fires once, after 10 seconds.
 * It calls a function which calls increment and then updates the timer
 * list to show that the timer has gone away once it fires.
 */
function add_after_timer ()
{
	after(10,#after_fn());
	update_timer_list();
}

/*
 * Function called by 10 sec. 'after' timer.  Increment the counter and
 * then update the timer list on the screen.
 */
function after_fn ()
{
	increment();
	update_timer_list();
}

/*
 * Function to remove a timer from the timers list.  Since we
 * created the timer list by using the stringc() of the timer
 * definition, we can simply pass the string returned the PtList
 * through the lisp parser to create an array.  The fifth element
 * of the array (array index 4) is the timer number, which we
 * can then pass to the cancel function.  We then delete the
 * timer from the array of elements in the PtList, and write the
 * array back to the PtList again.
 */
function remove_timer ()
{
	local sel, tmp_array, selection;

	sel = TimerList.selection_indexes[0];
	if (!nil_p(sel))
	{
		// Cancel the selected timer
		tmp_array = TimerList.items;
		str = TimerList.items[sel - 1];
		selection = parse_string (str);
		cancel(selection[4]);
		
		// Remove the selected timer from the list
		delete(tmp_array, sel - 1);
		TimerList.items = tmp_array;
		if (sel >= length (tmp_array))
			sel = length (tmp_array);
		TimerList.selection_indexes = array(sel);
	}
}

/*
 * Function which updates the TimerList list.  This function is called
 * whenever a timer is added or deleted, and also by the one_shot (after)
 * timer to clean up after itself.  The _timers_ variable is a special
 * internal variable which contains the definitions for all running
 * timers in the system.  This is one example of a variable name which
 * contains characters not allowed in a C identifier.  Care should be
 * taken to put white space around * and - operators, since Gamma will
 * interpret the string a_b as a variable name, not the multiplication
 * of a and b.
 */
function update_timer_list ()
{
	local i, len, tmp_array, selection;

	len = length (_timers_);
	tmp_array = make_array (len);
	
	for(i=0; i<len; i++)
	{
		tmp_array[i] = stringc(_timers_[i]);
	}

	/*
	 * Reset the timer list, but try to maintain the same selection
	 * position within the list.
	 */
	if (tmp_array)
	{
		selection = TimerList.selection_indexes;
		TimerList.items = tmp_array;
		TimerList.selection_indexes = selection;
	}
}

/*
 * Enter an infinite event loop.
 */
PtMainLoop ();
