/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */

package org.gnu.glib;

/**
 * Timer: an object that executes a <code>Fireable</code> target object's 
 * <code>fire</code> method at a specified interval.  
 *
 * For example, here's how to an application clock might be implemented,
 * where the application passes in an org.gnu.gtk.Label object as its
 * pane:
 *
 *      private final Label clockPane = (Label)glade.getWidget("clockLabel");
 *      private Timer clock = new Timer(1000, // one second
 *                                      new Fireable() {
 *          public boolean fire() {
 *             String dateStr = 
 *                 DateFormat.getDateInstance().format(new Date());
 *             clockPane.setText(dateStr);
 *             return true;  // continue firing
 *          }
 *      });
 *      clock.start();
 *
 * Note:  a Timer generates events on the application's GUI event queue.
 * It therefore is not accurate for short time periods.  It also should
 * only be used to directly fire short/fast methods.  Longer methods need
 * to be executed in a separate thread.
 *
 * @see org.gnu.glib.Fireable
 * @author Tom Ball
 */
public final class Timer {

    private int interval;
    private Fireable target;
	private int handle = -1;

    /**
     * Create a new Timer object.
     *
     * @param interval the time period between <code>fire</code>
     *                 method executions, in thousandths of a second.
     * @param target   the object whose fire() method gets called after the
     *                 specified time period elapses.
     * @throws IllegalArgumentException if less than one.
     */
    public Timer(int interval, Fireable target) {
	if (interval <= 0)
	    throw new IllegalArgumentException("invalid time: " + interval);
	this.interval = interval;
	this.target = target;
    }

    /**
     * Returns the interval associated with this Timer.
     *
     * @return the time period between <code>fire</code>
     *         method executions, in thousandths of a second.
     */
    public final int getInterval() {
	return interval;
    }

    /**
     * Set the interval associated with this Timer.
     *
     * @param interval the time period between <code>fire</code>
     *                 method executions, in thousandths of a second.
     * @throws IllegalArgumentException if less than one.
     */
    public final void setInterval(int interval) {
	if (interval <= 0)
	    throw new IllegalArgumentException("invalid time: " + interval);
	this.interval = interval;
    }

    /**
     * Start this timer object; that is, begin executing its fire method
     * at its specified interval.
     */
    public final synchronized void start() {
    	handle = start_timer(interval);
    }

    /**
     * Returns whether this timer is running.
     *
     * @return true if this timer is currently running.
     */
    public final synchronized boolean isRunning() {
    	return handle != -1;
    }

    /**
     * Stop this timer object; that is, stop executing its fire method
     * at its specified interval.  This method does not need to be 
     * called if the <code>fire</code> method returned <code>false</code>.
     */
    public final synchronized void stop() {
    	stop_timer( handle );
    }

    /**
     * Do not call this method; it's only purpose is to ensure that
     * the timer is stopped before it is GC'd.
     */
    protected final void finalize() throws Throwable { 
	stop();
    }

    private native int start_timer(int interval);
    private native void stop_timer(int handle);
    private static native void initIDs();

    static {
	initIDs();
    }
}
