/*************************************************************************
*
* PTimer
*
* Author: Stefan Pochmann
* Date: Nov 18, 2009
* Version: 1.0
*
* The "P" of "PTimer" is in a quantum superposition - until I decide,
* it stands for both "Pochmann" and "Puzzle".
*
* It's a simple timer very similar to the Speedstacks Stackmat. Keys
* 'x' and '/' (or Alt and CTRL) play the role of the stackmat sensors.
*
* Demo video: [url]http://www.youtube.com/watch?v=tZCo-33o2Pw&fmt=22[/url]
* Forum thread: [url]http://www.speedsolving.com/forum/showthread.php?t=16952[/url]
*
* I hope the code is self-explanatory cause I don't feel like explaining it.
*
*************************************************************************/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PTimer extends JFrame {
public static void main ( String[] args ) throws Exception {
new PTimer();
}
//--- The side lights and time display
Canvas left = new Canvas(), right = new Canvas();
JLabel middle = new JLabel();
PTimer () throws Exception {
//--- Full screen
setUndecorated( true );
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
setBounds( 0, 0, width, height );
//--- Left and right lights
left.setSize( width/20, 1 );
left.setBackground( Color.BLACK );
right.setSize( width/20, 1 );
right.setBackground( Color.BLACK );
//--- Middle display
middle.setOpaque( true );
middle.setForeground( Color.RED );
middle.setBackground( Color.BLACK );
middle.setHorizontalAlignment( SwingConstants.CENTER );
middle.setFont( new Font( "Serif", 0, width/4 ) );
middle.setText( "PTimer" );
//--- Show everything
getContentPane().add( left, BorderLayout.WEST );
getContentPane().add( middle );
getContentPane().add( right, BorderLayout.EAST );
setVisible( true );
//--- Dance!
phase = WAIT_FOR_HANDS;
while ( true ) {
//--- Wait 0.01 seconds, then determine passed time in hundreds of seconds
Thread.sleep( 10 );
long hs = ( System.currentTimeMillis() - startTime ) / 10;
//--- Go from WAIT_FOR_GREEN to WAIT_FOR_START after 0.6 seconds
if ( phase == WAIT_FOR_GREEN && hs > 60 ) {
phase = WAIT_FOR_START;
showLight( left, true );
showLight( right, true );
}
// While running, display the passed time
if ( phase == WAIT_FOR_STOP )
middle.setText( String.format( "%d:%02d.%02d", hs/6000, hs/100%60, hs%100 ));
}
}
//--- The phase we're in
int phase;
int WAIT_FOR_HANDS = 1;
int WAIT_FOR_GREEN = 2;
int WAIT_FOR_START = 3;
int WAIT_FOR_STOP = 4;
int WAIT_FOR_RELEASE = 5;
//--- Start time, status of buttons
long startTime;
boolean leftPressed, rightPressed;
//--- Show a light (black or red or green)
void showLight ( Canvas light, boolean pressed ) {
light.setBackground( pressed ? ( phase == WAIT_FOR_START ? Color.GREEN : Color.RED ) : Color.BLACK );
}
//--- Handle key events
protected void processKeyEvent ( KeyEvent e ) {
//--- Determine button status
if( e.getKeyChar() == 'x' || e.getKeyCode() == e.VK_ALT )
leftPressed = e.getID() != e.KEY_RELEASED;
if( e.getKeyChar() == '/' || e.getKeyCode() == e.VK_CONTROL )
rightPressed = e.getID() != e.KEY_RELEASED;
boolean bothPressed = leftPressed && rightPressed;
//--- Handle phase transitions
if ( phase == WAIT_FOR_HANDS && bothPressed ) {
startTime = System.currentTimeMillis();
phase = WAIT_FOR_GREEN;
}
if ( phase == WAIT_FOR_GREEN && ! bothPressed ) {
phase = WAIT_FOR_HANDS;
middle.setText( "PTimer" );
}
if ( phase == WAIT_FOR_START && ! bothPressed ) {
startTime = System.currentTimeMillis();
phase = WAIT_FOR_STOP;
}
if ( phase == WAIT_FOR_STOP && bothPressed )
phase = WAIT_FOR_RELEASE;
if ( phase == WAIT_FOR_RELEASE && ! bothPressed )
phase = WAIT_FOR_HANDS;
//--- Show the lights
showLight( left, leftPressed );
showLight( right, rightPressed );
}
}