package stopwatch;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * Provides a simple one-window display for a timer. Instantiate, then call the
 * <code>setTime()</code> method on an as-desired basis to update the displayed
 * time. Modified from an original version by Dr. Scott Knight.
 * 
 * @author Greg Phillips
 * @version 7 February 2006
 *
 */
public class TimeDisplay extends JFrame {

	private static final long serialVersionUID = 1L;
	private JLabel timeField = new JLabel("00000.00 sec");

	/**
	 * Creates the timer panel with an initial display of 
	 * "00000.00 sec" and makes it visible.
	 */
	TimeDisplay() {
		super("e-stopwatch");
		JPanel mainPanel = new JPanel();
		mainPanel.add(timeField);
		getContentPane().add(mainPanel);
		setSize(300, 100);
		setVisible(true);
	}
	
	/**
	 * Updates the displayed time to the parameter followed by "sec".
	 * Performs the update in the AWT event thread.
	 * 
	 * @param newTime the time to be displayed, in seconds
	 */
	public void setTime(double newTime) {
		/*
		 * We shouldn't simply call timeField.setText() because
		 * this method may/will be called by a thread outside the
		 * ATW event loop, which could cause subtle and hard-to debug
		 * race conditions. Instead, we post a message to the AWT
		 * event loop using invokeLater(). The message consists of
		 * a Runnable object whose run() method does what we need.
		 * Isn't multi-threaded GUI programming fun?
		 * 
		 * For all the gory details see:
		 * http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#event_dispatching
		 */
		final double time = newTime; // must be final to allow use in Runnable
		Runnable doSetText = new Runnable(){
			public void run() {
				timeField.setText(time + " sec");
			}
		};
		SwingUtilities.invokeLater(doSetText);
	}

	public static void main(String[] args) {
		TimeDisplay newDisplay = new TimeDisplay();
		// ensure the application closes when the window closes
		newDisplay.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		newDisplay.setTime(10.5);
	}
}