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 }