Source code: myComponents/JDoubleField.java
1 /* Evolvo - Image Generator
2 * Copyright (C) 2000 Andrew Molloy
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /*
20 * @(#)JDoubleField.java 0.1 08/19/2000
21 */
22 package myComponents;
23
24 import javax.swing.JTextField;
25 import java.awt.event.*;
26 import javax.swing.text.*;
27 import javax.swing.event.*;
28
29
30 /**
31 * Extends JTextField, allowing only numbers to be entered.
32 * These numbers may be floating point (double, specifically), but are restricted to a specified range.
33 *
34 * @version 1.1 08/19/2000
35 * @author Andy Molloy
36 */
37 public class JDoubleField extends JTextField implements ActionListener, ChangeListener
38 {
39 /** Range model used to determine valid values for the text field. */
40 DoubleBoundedRangeModel dbrm;
41
42 /** Default constructor. */
43 public JDoubleField()
44 {
45 this(0.0, 0.0, 0.0, 1.0, 4, 6);
46 }
47
48 /** Class constuctor that takes DoubleBoundedRandeModel's parameters individually, and a column width. */
49 public JDoubleField(double v, double e, double min, double max, int p, int cols)
50 {
51 this(new DoubleBoundedRangeModel(v, e, min, max, p), cols);
52 }
53
54 /** Class constuctor that takes DoubleBoundedRandeModel's parameters individually, setting a default column width. */
55 public JDoubleField(double v, double e, double min, double max, int p)
56 {
57 this(new DoubleBoundedRangeModel(v, e, min, max, p), 6);
58 }
59
60 /** Class constructor that takes a DoubleBoundedRangeModel and sets the column with to a default value. */
61 public JDoubleField(DoubleBoundedRangeModel dm)
62 {
63 this(dm, 6);
64 }
65
66 /** Class constructor which takes a DoubleBoundedRangeModel, and a column width. */
67 public JDoubleField(DoubleBoundedRangeModel dm, int cols)
68 {
69 super(cols);
70 dbrm = dm;
71 addActionListener(this);
72 addChangeListener(this);
73 setText("" + dbrm.getDoubleValue());
74 }
75
76 /** Creates a new DoubleDocument document model. */
77 protected Document createDefaultModel()
78 {
79 return new DoubleDocument();
80 }
81
82 /** Handles all recieved ActionEvents. */
83 public void actionPerformed(ActionEvent e)
84 {
85 try
86 {
87 setValue(Double.parseDouble(getText())); // Set the value to number in the text field.
88 }
89 catch (NumberFormatException ex)
90 {
91 select(0, getText().length()); // If the text field does not contain a valid number, reject the input and select all the text.
92 }
93 }
94
95 /** Handles all recieved ChangeEvents. */
96 public void stateChanged(ChangeEvent e)
97 {
98 setValue(dbrm.getDoubleValue()); // Set the value of the DoubleBoundedRangeModel
99 setText("" + dbrm.getDoubleValue()); // And display the number in the text field. We pull the number from the
100 // DoubleBoundedRangeModel because it restricts the number to its defined range.
101 }
102
103 /** Returns the current value of the text field as a double. */
104 public double getValue()
105 {
106 return dbrm.getDoubleValue();
107 }
108
109 /** Sets the value of the text field from a double. */
110 public void setValue(double newValue)
111 {
112 double oldValue = dbrm.getDoubleValue();
113 dbrm.setDoubleValue(newValue);
114 newValue = dbrm.getDoubleValue();
115 setText("" + dbrm.getDoubleValue()); // Retrieve the bounded value from the dbrm
116 select(0, getText().length()); // Select the entire text field.
117 firePropertyChange("value", oldValue, dbrm.getDoubleValue()); // Fire a PropertyChanged event
118 }
119
120 /** Adds a ChangeListener. */
121 public void addChangeListener(ChangeListener l)
122 {
123 dbrm.addChangeListener(l);
124 }
125
126 /** Removes a ChangeListener. */
127 public void removeChangeListener(ChangeListener l)
128 {
129 dbrm.removeChangeListener(l);
130 }
131
132 /** Defines a document model that restricts input to characters which may be used to define a double. */
133 static class DoubleDocument extends PlainDocument
134 {
135 /** The acceptable characters. */
136 byte[] validChars = new String("eE-+.0123456789").getBytes();
137 /** The number of acceptable characters. */
138 int vcLength = validChars.length;
139
140 /** Insert the given String into the document iff it is valid.
141 * @throws BadLocationException
142 */
143 public void insertString(int offset, String str, AttributeSet a) throws BadLocationException
144 {
145 byte[] strArray = str.getBytes();
146 boolean valid = true;
147
148 for (int strIndex = 0; strIndex < strArray.length ; strIndex++)
149 {
150 boolean internalValid = false;
151 for (int vcIndex = 0; vcIndex < vcLength; vcIndex++ )
152 {
153 if ( strArray[strIndex] == validChars[vcIndex] )
154 {
155 internalValid = true;
156 vcIndex = vcLength;
157 }
158 }
159 if (internalValid == false)
160 {
161 valid = false;
162 strIndex = strArray.length;
163 }
164 }
165 if ( !valid )
166 {
167 return;
168 }
169 super.insertString(offset, str, a);
170 }
171 };
172 }