1 /* 2 * The contents of this file are subject to the BT "ZEUS" Open Source 3 * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 4 * except in compliance with the Licence. You may obtain a copy of the Licence 5 * from $ZEUS_INSTALL/licence.html or alternatively from 6 * http://www.labs.bt.com/projects/agents/zeus/licence.htm 7 * 8 * Except as stated in Clause 7 of the Licence, software distributed under the 9 * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 10 * implied. See the Licence for the specific language governing rights and 11 * limitations under the Licence. 12 * 13 * The Original Code is within the package zeus.*. 14 * The Initial Developer of the Original Code is British Telecommunications 15 * public limited company, whose registered office is at 81 Newgate Street, 16 * London, EC1A 7AJ, England. Portions created by British Telecommunications 17 * public limited company are Copyright 1996-9. All Rights Reserved. 18 * 19 * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE 20 */ 21 22 package figtree.ui.components; 23 24 import javax.swing.*; 25 import javax.swing.event.*; 26 import javax.swing.text.AttributeSet; 27 import javax.swing.text.BadLocationException; 28 import javax.swing.text.Document; 29 import javax.swing.text.PlainDocument; 30 import java.awt.*; 31 import java.awt.event.FocusEvent; 32 import java.awt.event.FocusListener; 33 34 /** 35 * 36 * @version $Id$ 37 * 38 * $HeadURL$ 39 * 40 * $LastChangedBy$ 41 * $LastChangedDate$ 42 * $LastChangedRevision$ 43 */ 44 public class RealNumberField extends JTextField 45 implements FocusListener, DocumentListener { 46 47 protected static char MINUS = '-'; 48 protected static char PERIOD = '.'; 49 protected EventListenerList changeListeners = new EventListenerList(); 50 protected double min; 51 protected double max; 52 protected boolean range_check = false; 53 protected boolean range_checked = false; 54 RealNumberField()55 public RealNumberField() { 56 super(); 57 } 58 RealNumberField(double min, double max)59 public RealNumberField(double min, double max) { 60 this(); 61 this.min = min; 62 this.max = max; 63 range_check = true; 64 this.addFocusListener(this); 65 } 66 focusGained(FocusEvent evt)67 public void focusGained(FocusEvent evt) { 68 } 69 focusLost(FocusEvent evt)70 public void focusLost(FocusEvent evt) { 71 if (range_check && !range_checked) { 72 range_checked = true; 73 try { 74 double value = (Double.valueOf(getText())).doubleValue(); 75 if (value < min || value > max) { 76 errorMsg(); 77 return; 78 } 79 } catch (NumberFormatException e) { 80 errorMsg(); 81 return; 82 } 83 } 84 } 85 setText(Double obj)86 public void setText(Double obj) { 87 setText(obj.toString()); 88 } 89 setText(Integer obj)90 public void setText(Integer obj) { 91 setText(obj.toString()); 92 } 93 setText(Long obj)94 public void setText(Long obj) { 95 setText(obj.toString()); 96 } 97 errorMsg()98 protected void errorMsg() { 99 JOptionPane.showMessageDialog(this, 100 "Illegal entry\nValue must be between " + min + " and " + 101 max + " inclusive", "Error", JOptionPane.ERROR_MESSAGE); 102 } 103 setRange(double min, double max)104 public void setRange(double min, double max) { 105 this.min = min; 106 this.max = max; 107 range_check = true; 108 } 109 setValue(double value)110 public void setValue(double value) { 111 if (range_check) { 112 if (value < min || value > max) { 113 errorMsg(); 114 return; 115 } 116 } 117 setText(Double.toString(value)); 118 } 119 getValue()120 public Double getValue() { 121 try { 122 return new Double(getText()); 123 } catch (NumberFormatException e) { 124 return null; 125 } 126 } 127 getValue(double def)128 public Double getValue(double def) { 129 try { 130 return new Double(getText()); 131 } catch (NumberFormatException e) { 132 return new Double(def); 133 } 134 } 135 createDefaultModel()136 protected Document createDefaultModel() { 137 Document doc = new RealNumberFieldDocument(); 138 doc.addDocumentListener(this); 139 return doc; 140 } 141 insertUpdate(DocumentEvent e)142 public void insertUpdate(DocumentEvent e) { 143 range_checked = false; 144 fireChanged(); 145 } 146 removeUpdate(DocumentEvent e)147 public void removeUpdate(DocumentEvent e) { 148 range_checked = false; 149 fireChanged(); 150 } 151 changedUpdate(DocumentEvent e)152 public void changedUpdate(DocumentEvent e) { 153 range_checked = false; 154 fireChanged(); 155 } 156 157 static char[] numberSet = { 158 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 159 }; 160 161 class RealNumberFieldDocument extends PlainDocument { insertString(int offs, String str, AttributeSet a)162 public void insertString(int offs, String str, AttributeSet a) 163 throws BadLocationException { 164 165 if (str == null) return; 166 str = str.trim(); 167 168 int length = getLength(); 169 String buf = getText(0, offs) + str + getText(offs, length - offs); 170 buf = buf.trim().toUpperCase(); 171 char[] array = buf.toCharArray(); 172 173 if (array.length > 0) { 174 if (array[0] != MINUS && !member(array[0], numberSet) && 175 array[0] != PERIOD) { 176 Toolkit.getDefaultToolkit().beep(); 177 return; 178 } 179 } 180 181 boolean period_found = (array.length > 0 && array[0] == PERIOD); 182 boolean exponent_found = false; 183 int exponent_index = -1; 184 boolean exponent_sign_found = false; 185 186 for (int i = 1; i < array.length; i++) { 187 if (!member(array[i], numberSet)) { 188 if (!period_found && array[i] == PERIOD) { 189 period_found = true; 190 } else if (!exponent_found && array[i] == 'E') { 191 exponent_found = true; 192 exponent_index = i; 193 } else if (exponent_found && i == (exponent_index + 1) && !exponent_sign_found && array[i] == '-') { 194 exponent_sign_found = true; 195 } else { 196 Toolkit.getDefaultToolkit().beep(); 197 return; 198 } 199 } 200 } 201 super.insertString(offs, str, a); 202 } 203 } 204 member(char item, char[] array)205 static boolean member(char item, char[] array) { 206 for (int i = 0; i < array.length; i++) 207 if (array[i] == item) return true; 208 return false; 209 } 210 //------------------------------------------------------------------------ 211 // Event Methods 212 //------------------------------------------------------------------------ 213 addChangeListener(ChangeListener x)214 public void addChangeListener(ChangeListener x) { 215 changeListeners.add(ChangeListener.class, x); 216 } 217 removeChangeListener(ChangeListener x)218 public void removeChangeListener(ChangeListener x) { 219 changeListeners.remove(ChangeListener.class, x); 220 } 221 fireChanged()222 protected void fireChanged() { 223 ChangeEvent c = new ChangeEvent(this); 224 Object[] listeners = changeListeners.getListenerList(); 225 for (int i = listeners.length - 2; i >= 0; i -= 2) { 226 if (listeners[i] == ChangeListener.class) { 227 ChangeListener cl = (ChangeListener) listeners[i + 1]; 228 cl.stateChanged(c); 229 } 230 } 231 } 232 } 233