001 package util.swing;
002
003 import javax.swing.*;
004 import javax.swing.event.*;
005 import javax.swing.text.*;
006
007 /**
008 * A {@link JTextField} that will allow only int values within a certain range to be entered.
009 *
010 * <p><b>Note:</b> This class is not meant to be serialized!</p>
011 *
012 * @author Steffen Zschaler
013 * @version 2.0 28/07/1999
014 * @since v2.0
015 */
016 public class JIntInput extends JTextField {
017
018 /**
019 * The current value observer. The current value can always be found as the first element of the array.
020 *
021 * @serial This class is not meant to be serialized!
022 */
023 protected int[] m_anValue;
024
025 /**
026 * The default value of the input field.
027 *
028 * @serial This class is not meant to be serialized!
029 */
030 protected int m_nDefault = 0;
031
032 /**
033 * The minimum value.
034 *
035 * @serial This class is not meant to be serialized!
036 */
037 protected int m_nMinimum;
038
039 /**
040 * The maximum value.
041 *
042 * @serial This class is not meant to be serialized!
043 */
044 protected int m_nMaximum;
045
046 /**
047 * Create a new JIntInput. The minimum and maximum values default to {@link java.lang.Integer#MIN_VALUE} and
048 * {@link java.lang.Integer#MAX_VALUE}, resp.
049 *
050 * @param anValue the value observer the current value of the input field can be found as the first element
051 * of the array at any time.
052 * @param nDefault the default value of the input line.
053 */
054 public JIntInput(int[] anValue, int nDefault) {
055 this(anValue, nDefault, Integer.MIN_VALUE, Integer.MAX_VALUE);
056 }
057
058 /**
059 * Create a new JIntInput.
060 *
061 * @param anValue the value observer the current value of the input field can be found as the first element
062 * of the array at any time.
063 * @param nDefault the default value of the input line.
064 * @param nMinimum the minimum input value.
065 * @param nMaximum the maximum input value.
066 */
067 public JIntInput(int[] anValue, int nDefault, int nMinimum, int nMaximum) {
068
069 super("0");
070 // The value set here can be anything, because we set the actual value at the end of this constructor
071 // This is done, so that everything is properly initialized when the setText method is called.
072
073 m_anValue = anValue;
074 m_nMinimum = nMinimum;
075 m_nMaximum = nMaximum;
076 m_nDefault = ((nDefault >= m_nMinimum) ? ((nDefault <= m_nMaximum) ? (nDefault) : (m_nMaximum)) :
077 (m_nMinimum));
078 m_anValue[0] = m_nDefault;
079
080 getDocument().addDocumentListener(new DocumentListener() {
081 public void changedUpdate(DocumentEvent e) {
082 performUpdate();
083 }
084
085 public void insertUpdate(DocumentEvent e) {
086 performUpdate();
087 }
088
089 public void removeUpdate(DocumentEvent e) {
090 performUpdate();
091 }
092
093 private void performUpdate() {
094 String sText = getText();
095 if (sText == "") {
096 sText = Integer.toString(m_nDefault);
097 }
098
099 try {
100 m_anValue[0] = Integer.parseInt(sText);
101 }
102 catch (NumberFormatException nfe) {}
103 }
104 });
105
106 setHorizontalAlignment(RIGHT);
107
108 // we set the text again, because when this is done in the super class constructor, the minimum and maximum values
109 // have not yet been set correctly.
110 setText(Integer.toString(m_nDefault));
111 }
112
113 /**
114 * Create and return the input fields document. This will create a document that allows only int values
115 * within the current range to be entered.
116 */
117 protected Document createDefaultModel() {
118 return new PlainDocument() {
119 private boolean m_fDidSpecialRemove = false;
120
121 public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
122
123 if (m_fDidSpecialRemove) {
124 if (getLength() > 0) {
125 super.remove(0, getLength());
126 }
127
128 offs = 0;
129 m_fDidSpecialRemove = false;
130 }
131
132 if (str == null) {
133 return;
134 }
135
136 String sText = getText(0, getLength());
137
138 if (sText == null) {
139 sText = "";
140 offs = 0;
141 }
142
143 sText = new StringBuffer(sText).insert(offs, str).toString();
144
145 try {
146 int nCounter = Integer.parseInt(sText);
147
148 if (nCounter < m_nMinimum) {
149 return;
150 }
151
152 if (nCounter > m_nMaximum) {
153 return;
154 }
155
156 super.insertString(offs, str, a);
157 }
158 catch (NumberFormatException nfe) {
159 if (getLength() == 0) {
160 super.insertString(0, Integer.toString(m_nDefault), a);
161 }
162 }
163 }
164
165 public void remove(int offs, int len) throws BadLocationException {
166
167 String sText = getText(0, getLength());
168
169 if (sText == null) {
170 return;
171 }
172
173 sText = new StringBuffer(sText).delete(offs, offs + len).toString();
174
175 if (sText.equals("")) {
176 sText = null;
177 }
178
179 try {
180 int nCounter = 0;
181
182 if (sText != null) {
183 nCounter = Integer.parseInt(sText);
184 }
185
186 if ((nCounter < m_nMinimum) || (nCounter > m_nMaximum) || (sText == null)) {
187 super.remove(0, getLength());
188 super.insertString(0, Integer.toString(m_nDefault), null);
189
190 m_fDidSpecialRemove = true;
191 } else {
192 super.remove(offs, len);
193
194 m_fDidSpecialRemove = false;
195 }
196 }
197 catch (NumberFormatException nfe) {
198 m_fDidSpecialRemove = false;
199 }
200 }
201 };
202 }
203 }