1 package org.jcurl.demo.tactics;
2
3 import java.awt.event.FocusEvent;
4 import java.awt.event.FocusListener;
5 import java.awt.event.ItemEvent;
6 import java.awt.event.ItemListener;
7
8 import javax.swing.BoxLayout;
9 import javax.swing.DefaultComboBoxModel;
10 import javax.swing.JComboBox;
11 import javax.swing.JComponent;
12 import javax.swing.JLabel;
13 import javax.swing.JSpinner;
14 import javax.swing.SpinnerNumberModel;
15 import javax.swing.JSpinner.DefaultEditor;
16 import javax.swing.event.ChangeEvent;
17 import javax.swing.event.ChangeListener;
18
19 import org.apache.commons.logging.Log;
20 import org.jcurl.core.api.ChangeSupport;
21 import org.jcurl.core.api.IChangeSupport;
22 import org.jcurl.core.api.Unit;
23 import org.jcurl.core.log.JCLoggerFactory;
24
25
26
27
28
29
30
31 public class JSpinnerNumberUnit extends JComponent implements ItemListener,
32 FocusListener, ChangeListener, IChangeSupport {
33
34 private static final Log log = JCLoggerFactory
35 .getLogger(JSpinnerNumberUnit.class);
36
37 private static final long serialVersionUID = 7309659176999252671L;
38
39 private static double convert(final double v, final Unit src, final Unit dst) {
40 if (src == dst || src == null || src == Unit.NONE || dst == null
41 || dst == Unit.NONE)
42 return v;
43 return src.convert(dst, v);
44 }
45
46 private static SpinnerNumberModel rescale(final Unit src, final Unit dst,
47 final SpinnerNumberModel m) {
48 if (m == null || dst == null || src == null || src == dst)
49 return m;
50 if (log.isDebugEnabled())
51 log.debug("Convert " + src + " -> " + dst + ":" + m.getValue()
52 + " -> " + src.convert(dst, m.getNumber().doubleValue()));
53 m.setValue(src.convert(dst, m.getNumber().doubleValue()));
54 m.setMinimum(src.convert(dst, ((Number) m.getMinimum()).doubleValue()));
55 m.setMaximum(src.convert(dst, ((Number) m.getMaximum()).doubleValue()));
56 return m;
57 }
58
59 private Unit base = null;
60 private final transient ChangeSupport change = new ChangeSupport(this);
61 private Unit[] choose = new Unit[0];
62 private final JComboBox combo;
63 private final JLabel label;
64 transient private double oldValueBase = Double.NaN;
65 private Unit unit = null;
66
67 private final JSpinner value;
68
69 private boolean valueIsAdjusting;
70
71 public JSpinnerNumberUnit() {
72 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
73 add(label = new JLabel("xxx"));
74 add(value = new JSpinner());
75 add(combo = new JComboBox(choose));
76 combo.addItemListener(this);
77 setBase(Unit.NONE);
78 setChoose();
79 }
80
81
82 public void addChangeListener(final ChangeListener l) {
83 change.addChangeListener(l);
84 }
85
86
87 public void focusGained(final FocusEvent e) {
88 setValueIsAdjusting(true);
89 }
90
91
92 public void focusLost(final FocusEvent e) {
93 setValueIsAdjusting(false);
94 }
95
96
97 public ChangeListener[] getChangeListeners() {
98 return change.getChangeListeners();
99 }
100
101 private DefaultEditor getEd() {
102 return (JSpinner.DefaultEditor) value.getEditor();
103 }
104
105
106 JComponent getLabel() {
107 return label;
108 }
109
110
111 public SpinnerNumberModel getModel() {
112 return (SpinnerNumberModel) value.getModel();
113 }
114
115
116 JComponent getSpinner() {
117 return value;
118 }
119
120
121 public Unit getUnit() {
122 if (true)
123 return unit;
124 else {
125 if (!combo.isVisible())
126 return Unit.NONE;
127 final Unit old = (Unit) combo.getSelectedItem();
128 if (old == null)
129 return Unit.NONE;
130 return old;
131 }
132 }
133
134
135 JComponent getUnitCombo() {
136 return combo;
137 }
138
139
140 public double getValue() {
141 return convert(getModel().getNumber().doubleValue(), getUnit(), base);
142 }
143
144
145
146
147
148 public boolean getValueIsAdjusting() {
149 return change.getValueIsAdjusting();
150 }
151
152
153 public void itemStateChanged(final ItemEvent e) {
154 if (e.getSource() == combo)
155 setUnit((Unit) e.getItem());
156 }
157
158
159 public void removeChangeListener(final ChangeListener l) {
160 change.removeChangeListener(l);
161 }
162
163
164 public void setBase(final Unit base) {
165 final Unit old = this.base;
166 if (old == base)
167 return;
168 if (choose == null || choose.length == 0)
169 setChoose(base);
170 firePropertyChange("base", old, this.base = base);
171 }
172
173
174
175
176
177
178
179
180 public void setChoose(final Unit... choose) {
181 this.choose = choose;
182 combo.setModel(new DefaultComboBoxModel(this.choose));
183 combo.setVisible(this.choose != null && this.choose.length > 0);
184 combo.setEnabled(combo.isVisible() && choose.length > 1);
185 unit = (Unit) combo.getSelectedItem();
186 }
187
188 @Override
189 public void setEnabled(boolean enabled) {
190 if (!enabled) {
191 label.setEnabled(enabled);
192 value.setEnabled(enabled);
193 combo.setEnabled(enabled);
194 } else {
195 label.setEnabled(label.isVisible());
196 value.setEnabled(value.isVisible());
197 combo.setEnabled(combo.isVisible());
198 }
199 super.setEnabled(enabled);
200 }
201
202
203
204
205
206
207 public void setLabel(final String label) {
208 final String old = this.label.getText();
209 if (old == label)
210 return;
211 this.label.setText(label);
212 this.label.setVisible(label != null);
213 firePropertyChange("label", old, label);
214 }
215
216
217
218
219
220
221
222
223
224
225 public void setModel(final SpinnerNumberModel model) {
226 final SpinnerNumberModel old = getModel();
227 if (old == model)
228 return;
229 if (old != null) {
230
231 getEd().getTextField().removeFocusListener(this);
232
233 old.removeChangeListener(this);
234 }
235 oldValueBase = Double.NaN;
236 if (model != null) {
237 value.setModel(rescale(base, getUnit(), model));
238 oldValueBase = getValue();
239
240 getEd().getTextField().addFocusListener(this);
241
242 model.addChangeListener(this);
243 }
244 value.setVisible(model != null);
245 firePropertyChange("model", old, model);
246 }
247
248
249 public void setUnit(final Unit current) {
250 final Unit old = unit;
251 if (current == old)
252 return;
253 combo.setSelectedItem(unit = current);
254
255 rescale(old, unit, getModel());
256 firePropertyChange("unit", old, unit);
257 }
258
259 public void setValue(double value) {
260 if (oldValueBase == value)
261 return;
262
263 value = convert(value, base, getUnit());
264
265 oldValueBase = convert(value, getUnit(), base);
266 if (value == getModel().getNumber().doubleValue())
267 return;
268 this.value.setValue(value);
269 }
270
271
272 public void setValueIsAdjusting(final boolean valueIsAdjusting) {
273 final boolean old = this.valueIsAdjusting;
274 if (old == valueIsAdjusting)
275 return;
276 firePropertyChange("valueIsAdjusting", old,
277 this.valueIsAdjusting = valueIsAdjusting);
278 }
279
280
281 public void stateChanged(final ChangeEvent e) {
282 if (e.getSource() == getModel()) {
283 final double v = getValue();
284 if (oldValueBase == v)
285 return;
286 oldValueBase = v;
287 change.fireStateChanged();
288 }
289 }
290 }