/* * JSpinField.java - A spin field using a JSpinner (JDK 1.4) * Copyright (C) 2004 Kai Toedter * kai@toedter.com * www.toedter.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package accessories.plugins.time; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * JSpinField is a numeric field with 2 spin buttons to increase or decrease the * value. It has the same interface as the "old" JSpinField but uses a JSpinner * internally (since J2SE SDK 1.4) rather than a scrollbar for emulating the * spin buttons. * * @author Kai Toedter * @version $LastChangedRevision: 85 $ * @version $LastChangedDate: 2006-04-28 13:50:52 +0200 (Fr, 28 Apr 2006) $ */ public class JSpinField extends JPanel implements ChangeListener, CaretListener, ActionListener, FocusListener { private static final long serialVersionUID = 1694904792717740650L; protected JSpinner spinner; /** the text (number) field */ protected JTextField textField; protected int min; protected int max; protected int value; protected Color darkGreen; /** * Default JSpinField constructor. The valid value range is between * Integer.MIN_VALUE and Integer.MAX_VALUE. The initial value is 0. */ public JSpinField() { this(Integer.MIN_VALUE, Integer.MAX_VALUE); } /** * JSpinField constructor with given minimum and maximum vaues and initial * value 0. */ public JSpinField(int min, int max) { super(); setName("JSpinField"); this.min = min; if (max < min) max = min; this.max = max; value = 0; if (value < min) value = min; if (value > max) value = max; darkGreen = new Color(0, 150, 0); setLayout(new BorderLayout()); textField = new JTextField(); textField.addCaretListener(this); textField.addActionListener(this); textField.setHorizontalAlignment(SwingConstants.RIGHT); textField.setBorder(BorderFactory.createEmptyBorder()); textField.setText(Integer.toString(value)); textField.addFocusListener(this); spinner = new JSpinner() { private static final long serialVersionUID = -6287709243342021172L; private JTextField textField = new JTextField(); public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); return new Dimension(size.width, textField.getPreferredSize().height); } }; spinner.setEditor(textField); spinner.addChangeListener(this); // spinner.setSize(spinner.getWidth(), textField.getHeight()); add(spinner, BorderLayout.CENTER); } public void adjustWidthToMaximumValue() { JTextField testTextField = new JTextField(Integer.toString(max)); int width = testTextField.getPreferredSize().width; int height = testTextField.getPreferredSize().height; textField.setPreferredSize(new Dimension(width, height)); textField.revalidate(); } /** * Is invoked when the spinner model changes * * @param e * the ChangeEvent */ public void stateChanged(ChangeEvent e) { SpinnerNumberModel model = (SpinnerNumberModel) spinner.getModel(); int value = model.getNumber().intValue(); setValue(value); } /** * Sets the value attribute of the JSpinField object. * * @param newValue * The new value * @param updateTextField * true if text field should be updated */ protected void setValue(int newValue, boolean updateTextField, boolean firePropertyChange) { 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 (firePropertyChange) { firePropertyChange("value", oldValue, value); } } /** * Sets the value. This is a bound property. * * @param newValue * the new value * * @see #getValue */ public void setValue(int newValue) { setValue(newValue, true, true); spinner.setValue(new Integer(value)); } /** * Returns the value. * * @return the value value */ public int getValue() { return value; } /** * Sets the minimum value. * * @param newMinimum * the new minimum value * * @see #getMinimum */ public void setMinimum(int newMinimum) { min = newMinimum; } /** * Returns the minimum value. * * @return the minimum value */ public int getMinimum() { return min; } /** * Sets the maximum value and adjusts the preferred width. * * @param newMaximum * the new maximum value * * @see #getMaximum */ public void setMaximum(int newMaximum) { max = newMaximum; } /** * Sets the horizontal alignment of the displayed value. * * @param alignment * the horizontal alignment */ public void setHorizontalAlignment(int alignment) { textField.setHorizontalAlignment(alignment); } /** * Returns the maximum value. * * @return the maximum value */ public int getMaximum() { return max; } /** * Sets the font property. * * @param font * the new font */ public void setFont(Font font) { if (textField != null) { textField.setFont(font); } } /** * Sets the foreground * * @param fg * the foreground */ public void setForeground(Color fg) { if (textField != null) { textField.setForeground(fg); } } /** * After any user input, the value of the textfield is proofed. Depending on * being an integer, the value is colored green or red. * * @param e * the caret event */ public void caretUpdate(CaretEvent e) { try { int testValue = Integer.valueOf(textField.getText()).intValue(); if ((testValue >= min) && (testValue <= max)) { textField.setForeground(darkGreen); setValue(testValue, false, true); } 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(); } /** * After any user input, the value of the textfield is proofed. Depending on * being an integer, the value is colored green or red. If the textfield is * green, the enter key is accepted and the new value is set. * * @param e * Description of the Parameter */ public void actionPerformed(ActionEvent e) { if (textField.getForeground().equals(darkGreen)) { setValue(Integer.valueOf(textField.getText()).intValue()); } } /** * Enable or disable the JSpinField. * * @param enabled * The new enabled value */ public void setEnabled(boolean enabled) { super.setEnabled(enabled); spinner.setEnabled(enabled); textField.setEnabled(enabled); /* * Fixes the background bug 4991597 and sets the background explicitely * to a TextField.inactiveBackground. */ if (!enabled) { textField.setBackground(UIManager .getColor("TextField.inactiveBackground")); } } /** * Returns the year chooser's spinner (which allow the focus to be set to * it). * * @return Component the spinner or null, if the month chooser has no * spinner */ public Component getSpinner() { return spinner; } /** * Creates a JFrame with a JSpinField inside and can be used for testing. * * @param s * The command line arguments */ public static void main(String[] s) { JFrame frame = new JFrame("JSpinField"); frame.getContentPane().add(new JSpinField()); frame.pack(); frame.setVisible(true); } /* * (non-Javadoc) * * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent) */ public void focusGained(FocusEvent e) { } /** * The value of the text field is checked against a valid (green) value. If * valid, the value is set and a property change is fired. */ public void focusLost(FocusEvent e) { actionPerformed(null); } }