/* * File : SmallIntEditor.java * Created : 02-dec-2002 16:14 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details (see the LICENSE file). */ package edu.xtec.jclic.beans; import java.awt.BorderLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.NumberFormat; import java.text.ParseException; import javax.swing.*; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.08.29 */ public class SmallIntEditor extends JPanel implements ActionListener{ public static final String PROP_VALUE = "value"; private JButton plusButton, minusButton; private NumberField textFld; private int max, min, lastValue; private Toolkit toolkit; private NumberFormat integerFormatter; private int[] values; boolean editable; /** Creates a new instance of SmallIntEditor */ public SmallIntEditor() { //super(new BorderLayout()); //super(new FlowLayout(FlowLayout.RIGHT, 0, 0)); setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); setOpaque(false); editable=true; toolkit = Toolkit.getDefaultToolkit(); integerFormatter = NumberFormat.getNumberInstance(); integerFormatter.setParseIntegerOnly(true); max=10; min=0; plusButton=new JButton(new ImageIcon(getClass().getResource("/edu/xtec/resources/icons/plus.gif"))); //plusButton=new RepeaterButton(new ImageIcon(getClass().getResource("/edu/xtec/resources/icons/plus.gif"))); plusButton.setMnemonic('+'); plusButton.addActionListener(this); plusButton.setPreferredSize(new java.awt.Dimension(16, 16)); //minusButton=new RepeaterButton(new ImageIcon(getClass().getResource("/edu/xtec/resources/icons/minus.gif"))); minusButton=new JButton(new ImageIcon(getClass().getResource("/edu/xtec/resources/icons/minus.gif"))); minusButton.setMnemonic('-'); minusButton.addActionListener(this); minusButton.setPreferredSize(new java.awt.Dimension(16, 16)); textFld=new NumberField(4); textFld.setColumns(4); //textFld.setPreferredSize(new java.awt.Dimension(32, 16)); textFld.setHorizontalAlignment(JTextField.CENTER); textFld.setText("0"); //textFld.setEnabled(false); textFld.addActionListener(this); add(minusButton, BorderLayout.WEST); add(textFld, BorderLayout.CENTER); add(plusButton, BorderLayout.EAST); } @Override public void setToolTipText(String text){ super.setToolTipText(text); textFld.setToolTipText(text); plusButton.setToolTipText(text); minusButton.setToolTipText(text); } public void actionPerformed(ActionEvent ev){ int oldValue=lastValue; boolean btPlus=(plusButton==ev.getSource()); boolean btMinus=(minusButton==ev.getSource()); int delta= btPlus ? 1 : btMinus ? -1 : 0; if(delta!=0 && values!=null && values.length>0){ int p=0; while(p<values.length && oldValue>values[p]) p++; if(delta<0 || (p<values.length && values[p]==oldValue)) p+=delta; if(p>=0 && p<values.length) delta=values[p]-oldValue; else delta=0; } if(delta!=0){ setValue(getValue()+delta); } checkValueRanges(); checkEnabled(); lastValue=getValue(); firePropertyChange(PROP_VALUE, oldValue, lastValue); } private void checkEnabled(){ int value=getValue(); minusButton.setEnabled(isEnabled() && value>min); plusButton.setEnabled(isEnabled() && value<max); textFld.setEnabled(isEnabled() && editable); } @Override public void setEnabled(boolean b){ super.setEnabled(b); checkEnabled(); } public int getValue() { int retVal = 0; String s=textFld.getText(); if(s!=null && s.length()>0){ try { retVal = integerFormatter.parse(s).intValue(); } catch (ParseException e) { // This should never happen because insertString allows // only properly formatted data to get in the field. toolkit.beep(); System.err.println("Bad integer value " + s + ": " + e.getMessage()); } } return correctValue(retVal); } public void setValue(int value) { lastValue=correctValue(value); textFld.setText(integerFormatter.format(lastValue)); } public int correctValue(int value){ return Math.min(max, Math.max(min, value)); } private void checkValueRanges(){ int v=0; try { v = integerFormatter.parse(textFld.getText()).intValue(); } catch (ParseException e) { } if(v<min || v>max) setValue(correctValue(v)); } public void setEditColumns(int columns){ textFld.setColumns(columns); } public int getEditColumns(){ return textFld.getColumns(); } /** Getter for property max. * @return Value of property max. */ public int getMax() { return max; } /** Setter for property max. * @param max New value of property max. */ public void setMax(int max) { this.max = max; } /** Getter for property min. * @return Value of property min. */ public int getMin() { return min; } /** Setter for property min. * @param min New value of property min. */ public void setMin(int min) { this.min = min; } /** * Getter for property values. * @return Value of property values. */ public int[] getValues() { return this.values; } /** * Setter for property values. * @param values New value of property values. */ public void setValues(int[] values) { this.values = values; } /** * Getter for property editable. * @return Value of property editable. */ public boolean isEditable() { return editable; } /** * Setter for property editable. * @param editable New value of property editable. */ public void setEditable(boolean editable) { this.editable = editable; checkEnabled(); } class NumberField extends JTextField { public NumberField(int columns) { super(columns); } @Override protected Document createDefaultModel() { return new WholeNumberDocument(); } protected class WholeNumberDocument extends PlainDocument { @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { char[] source = str.toCharArray(); char[] result = new char[source.length]; int j = 0; for (int i = 0; i < result.length; i++) { if (Character.isDigit(source[i]) || source[i]=='-') result[j++] = source[i]; else { toolkit.beep(); } } super.insertString(offs, new String(result, 0, j), a); checkEnabled(); } @Override public void remove(int offs, int len) throws BadLocationException{ super.remove(offs, len); checkEnabled(); } } } }