
import java.beans.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JSpinField extends JPanel
	implements CaretListener, AdjustmentListener, ActionListener {

	public JSpinField() {
		super();
		min	= 0;
		max	= 100;
		value = 0;
		darkGreen = new Color( 0, 150, 0 );

		setLayout( new BorderLayout() );
		textField = new JTextField( "0" );
		textField.addCaretListener( this );
		textField.addActionListener( this );
		add( textField, BorderLayout.CENTER );
		scrollBar = new JScrollBar();
		scrollBar.setPreferredSize( new Dimension ( scrollBar.getPreferredSize().width,
			textField.getPreferredSize().height ) );
		scrollBar.setMinimum( min );
		scrollBar.setMaximum( max );
		scrollBar.setValue( max - value );
		scrollBar.setVisibleAmount( 0 );

		scrollBar.addAdjustmentListener( this );
		add( scrollBar, BorderLayout.EAST );
	}

	protected void setValue( int newValue, boolean updateTextField, boolean updateScrollbar ) {
		int oldValue = value;

		if( newValue < min )
			value = min;
		else if( newValue > max )
			value = max;
		else
			value = newValue;

		if( updateTextField ) {
			textField.setText( Integer.toString( value ) );
			textField.setForeground( Color.black );
		}

		if( updateScrollbar )
			scrollBar.setValue( max - value );

		firePropertyChange( "value", oldValue, value );
	}

	public void setValue( int newValue ) {
		setValue( newValue, true, true );
	}

	public int getValue() {
		return value;
	}

	public void setMinimum( int newMinimum ) {
		min = newMinimum;
		scrollBar.setMinimum( min );
	}

	public int getMinimum() {
		return min;
	}

	public void setMaximum( int newMaximum ) {
		max = newMaximum;
		scrollBar.setMaximum( max );
	}

	public int getMaximum() {
		return max;
	}

	public void setFont( Font font ) {
		if( textField != null )
		textField.setFont( font );
	}

	public void setForeground( Color fg) {
		if( textField != null )
		textField.setForeground( fg);
	}

	public void caretUpdate( CaretEvent e ) {
		try {
			int testValue = Integer.valueOf( textField.getText() ).intValue();

			if( (testValue >= min ) && ( testValue <= max ) ) {
				textField.setForeground( darkGreen );
			}
			else {
				textField.setForeground( Color.red );
			}
		}
		catch( Exception ex ) {
			if( ex instanceof NumberFormatException )
				textField.setForeground( Color.red );

			// Ignore all other exceptions, e.g. illegal state exception
		}
		textField.repaint();
	}

	public void adjustmentValueChanged( AdjustmentEvent e ) {
		setValue( max - e.getValue(), true, false );
	}

	public void actionPerformed( ActionEvent e ) {
		if( textField.getForeground().equals( darkGreen ) )
		setValue( Integer.valueOf( textField.getText() ).intValue() );
	}

	static public void main( String[] s ) {
		JFrame frame = new JFrame( "JSpinField" );
		frame.getContentPane().add( new JSpinField() );
		frame.pack();
		frame.setVisible( true );
	}

	private JTextField	textField;
	private JScrollBar	scrollBar;
	private Color		darkGreen;
	private int			min;
	private int			max;
	private int			value;
}
