1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.jcurl.demo.tactics;
21
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.awt.event.FocusEvent;
25 import java.awt.event.FocusListener;
26 import java.awt.event.ItemEvent;
27 import java.awt.event.ItemListener;
28 import java.awt.geom.Point2D;
29 import java.beans.PropertyChangeEvent;
30 import java.beans.PropertyChangeListener;
31
32 import javax.swing.BorderFactory;
33 import javax.swing.BoundedRangeModel;
34 import javax.swing.Box;
35 import javax.swing.BoxLayout;
36 import javax.swing.ButtonGroup;
37 import javax.swing.JComboBox;
38 import javax.swing.JComponent;
39 import javax.swing.JPanel;
40 import javax.swing.JRadioButton;
41 import javax.swing.JSpinner;
42 import javax.swing.SpinnerNumberModel;
43 import javax.swing.event.ChangeEvent;
44 import javax.swing.event.ChangeListener;
45
46 import org.apache.commons.logging.Log;
47 import org.jcurl.core.api.ComputedTrajectorySet;
48 import org.jcurl.core.api.IceSize;
49 import org.jcurl.core.api.RockSet;
50 import org.jcurl.core.api.Unit;
51 import org.jcurl.core.log.JCLoggerFactory;
52 import org.jcurl.core.ui.BroomPromptModel;
53 import org.jcurl.core.ui.ChangeManager;
54 import org.jcurl.core.ui.JSpinnerBoundedRange;
55 import org.jcurl.core.ui.TrajectoryBroomPromptWrapper;
56 import org.jcurl.core.ui.BroomPromptModel.HandleMemento;
57 import org.jcurl.core.ui.BroomPromptModel.IndexMemento;
58 import org.jcurl.core.ui.BroomPromptModel.SplitMemento;
59 import org.jcurl.core.ui.BroomPromptModel.XYMemento;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public class BroomPromptSwingBean extends JComponent implements HasChanger,
82 ItemListener, FocusListener, ChangeListener, ActionListener,
83 PropertyChangeListener {
84
85 private static final Log log = JCLoggerFactory
86 .getLogger(BroomPromptSwingBean.class);
87 private static final long serialVersionUID = -3512129363499720146L;
88 private static final boolean UseJSpinnerBoundedRange = true;
89 private BroomPromptModel broom;
90 private ChangeManager changer;
91 private final JRadioButton dark, light;
92 private final JComponent dt;
93 private SplitMemento first = null;
94 private transient XYMemento firstXY = null;
95 private final JRadioButton in, out;
96 private final JComboBox rock;
97 private final JSpinner split;
98 private final JSpinnerBoundedRange split2;
99 private final JSpinnerNumberUnit x;
100
101 private final JSpinnerNumberUnit y;
102
103 public BroomPromptSwingBean() {
104 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
105
106 final Box b = Box.createVerticalBox();
107 {
108 final JPanel tb = new JPanel();
109 tb.setLayout(new BoxLayout(tb, BoxLayout.X_AXIS));
110 tb.setBorder(BorderFactory.createTitledBorder("Active"));
111 tb
112 .add(rock = new JComboBox(new Object[] { 1, 2, 3, 4, 5, 6,
113 7, 8 }));
114 rock.setPrototypeDisplayValue(8);
115 rock.addItemListener(this);
116 dark = new JRadioButton("dark");
117 dark.addActionListener(this);
118 light = new JRadioButton("light");
119 light.addActionListener(this);
120 final ButtonGroup bg = new ButtonGroup();
121 bg.add(dark);
122 bg.add(light);
123 tb.add(dark);
124 tb.add(light);
125 b.add(tb);
126 }
127 {
128 final JPanel tb = new JPanel();
129 tb.setLayout(new BoxLayout(tb, BoxLayout.X_AXIS));
130 tb.setBorder(BorderFactory.createTitledBorder("Handle"));
131 in = new JRadioButton("In Turn");
132 in.addActionListener(this);
133 out = new JRadioButton("Out Turn");
134 out.addActionListener(this);
135 final ButtonGroup bg = new ButtonGroup();
136 bg.add(in);
137 bg.add(out);
138 tb.add(out);
139 tb.add(in);
140 tb.add(Box.createHorizontalGlue());
141 b.add(tb);
142 }
143 {
144 final JPanel tb = new JPanel();
145 tb.setLayout(new BoxLayout(tb, BoxLayout.X_AXIS));
146 tb.setBorder(BorderFactory.createTitledBorder("Split Time"));
147
148 if (UseJSpinnerBoundedRange) {
149 split2 = new JSpinnerBoundedRange();
150 split2.addFocusListener(this);
151 split = null;
152 } else {
153 split2 = null;
154 split = new JSpinner();
155
156 split.addFocusListener(this);
157 final JSpinner.NumberEditor ed = (JSpinner.NumberEditor) split
158 .getEditor();
159 ed.addFocusListener(this);
160 ed.getTextField().addFocusListener(this);
161 }
162
163 tb.add(split2);
164
165 tb.add(dt = new JComboBox(new Object[] { "1/1000 sec", "1/100 sec",
166 "1/10 sec", "sec" }));
167 tb.add(Box.createHorizontalGlue());
168 b.add(tb);
169 dt.setEnabled(false);
170 }
171 {
172 final JPanel p = new JPanel();
173 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
174 p.setBorder(BorderFactory.createTitledBorder("Broom Position"));
175 {
176 x = new JSpinnerNumberUnit();
177 x.setLabel("x: ");
178 x.setBase(Unit.METER);
179 x.setChoose(Unit.FOOT, Unit.INCH, Unit.CENTIMETER, Unit.METER);
180 x.setModel(new SpinnerNumberModel(0.0, -IceSize.SIDE_2_CENTER,
181 IceSize.SIDE_2_CENTER, 0.1));
182 x.addChangeListener(this);
183 x.addPropertyChangeListener(this);
184 p.add(x);
185 }
186 {
187 y = new JSpinnerNumberUnit();
188 y.setLabel("y: ");
189 y.setBase(Unit.METER);
190 y.setChoose(Unit.FOOT, Unit.INCH, Unit.CENTIMETER, Unit.METER);
191 y.setModel(new SpinnerNumberModel(0.0, -IceSize.BACK_2_TEE,
192 IceSize.HOG_2_TEE, 0.1));
193 y.addChangeListener(this);
194 y.addPropertyChangeListener(this);
195 p.add(y);
196 }
197 b.add(p);
198 }
199 this.add(b);
200 }
201
202 public void actionPerformed(final ActionEvent e) {
203 if (log.isDebugEnabled())
204 log.debug(e.getSource());
205 if (e.getSource() == dark || e.getSource() == light) {
206 updateIndex();
207 return;
208 }
209 if (e.getSource() == in || e.getSource() == out) {
210 updateHandle();
211 return;
212 }
213 log.warn("Unprocessed event from " + e.getSource());
214 }
215
216 private int findIndex() {
217 final int idx8 = rock.getSelectedIndex();
218 if (idx8 < 0)
219 return -1;
220 if (dark.isSelected())
221 return RockSet.toIdx16(true, idx8);
222 if (light.isSelected())
223 return RockSet.toIdx16(false, idx8);
224 return -1;
225 }
226
227 public void focusGained(final FocusEvent e) {
228 log.debug(e.getSource());
229 if (e.getSource() == split2) {
230 if (broom == null || broom.getSplitTimeMillis() == null)
231 return;
232 first = new SplitMemento(broom, broom.getSplitTimeMillis()
233 .getValue());
234 } else
235 log.warn("Unprocessed event from " + e.getSource());
236 }
237
238 public void focusLost(final FocusEvent e) {
239 if (e.getSource() == split2) {
240 if (broom == null || broom.getSplitTimeMillis() == null)
241 return;
242 getChanger().undoable(
243 first,
244 new SplitMemento(broom, broom.getSplitTimeMillis()
245 .getValue()));
246 first = null;
247 } else
248 log.warn("Unprocessed event from " + e.getSource());
249 }
250
251 public BroomPromptModel getBroom() {
252 return broom;
253 }
254
255 public ChangeManager getChanger() {
256 return ChangeManager.getTrivial(changer);
257 }
258
259 public void itemStateChanged(final ItemEvent e) {
260 if (log.isDebugEnabled())
261 log.debug(e.getSource());
262 if (e.getSource() == rock) {
263 updateIndex();
264 return;
265 }
266 log.warn("Unprocessed event from " + e.getSource());
267 }
268
269 public void propertyChange(final PropertyChangeEvent evt) {
270 if (log.isDebugEnabled())
271 log.debug(evt.getSource());
272 if (evt.getSource() == broom) {
273 if ("idx16".equals(evt.getPropertyName()))
274 syncM2V(broom == null ? -1 : broom.getIdx16());
275 else if ("outTurn".equals(evt.getPropertyName()))
276 syncM2V(broom == null ? null : broom.getOutTurn());
277 else if ("splitTimeMillis".equals(evt.getPropertyName()))
278 syncM2V(broom == null ? null : broom.getSplitTimeMillis());
279 else if ("broom".equals(evt.getPropertyName()))
280 syncM2V(broom == null ? null : broom.getBroom());
281 } else if (evt.getSource() == x || evt.getSource() == y) {
282 if ("valueIsAdjusting".equals(evt.getPropertyName()))
283 if (Boolean.TRUE.equals(evt.getNewValue()))
284 firstXY = new XYMemento(broom, broom.getBroom());
285 else {
286 if (Boolean.FALSE.equals(evt.getNewValue()))
287 getChanger()
288 .undoable(
289 firstXY,
290 new XYMemento(broom, x.getValue(), y
291 .getValue()));
292 firstXY = null;
293 }
294 } else
295 log.warn("Unprocessed event from " + evt.getSource());
296 }
297
298 public void setBroom(final BroomPromptModel broom) {
299 log.debug(broom);
300 if (this.broom == broom)
301 return;
302 if (this.broom != null)
303 this.broom.removePropertyChangeListener(this);
304 this.broom = broom;
305 syncM2V(this.broom == null ? -1 : this.broom.getIdx16());
306 syncM2V(this.broom == null ? null : this.broom.getOutTurn());
307 syncM2V(this.broom == null ? null : this.broom.getSplitTimeMillis());
308 syncM2V(this.broom == null ? null : this.broom.getBroom());
309 if (this.broom != null)
310 this.broom.addPropertyChangeListener(this);
311 }
312
313 public void setChanger(final ChangeManager changer) {
314 final ChangeManager old = this.changer;
315 if (old == changer)
316 return;
317 firePropertyChange("changer", old, this.changer = changer);
318 }
319
320 @Override
321 public void setEnabled(boolean enabled) {
322 super.setEnabled(enabled);
323 rock.setEnabled(enabled);
324 dark.setEnabled(enabled);
325 light.setEnabled(enabled);
326
327 in.setEnabled(enabled);
328 out.setEnabled(enabled);
329
330 if (UseJSpinnerBoundedRange)
331 split2.setEnabled(enabled);
332 else
333 split.setEnabled(enabled);
334
335 x.setEnabled(enabled);
336 y.setEnabled(enabled);
337
338 enabled = false;
339 dt.setEnabled(enabled);
340 }
341
342 public void stateChanged(final ChangeEvent e) {
343 if (log.isDebugEnabled())
344 log.debug(e.getSource());
345 if (e.getSource() == x) {
346 final double nx = x.getValue();
347 if (broom.getBroom().getX() != nx)
348 getChanger().temporary(
349 new XYMemento(broom, nx, broom.getBroom().getY()));
350 } else if (e.getSource() == y) {
351 final double ny = y.getValue();
352 if (broom.getBroom().getY() != ny)
353 getChanger().temporary(
354 new XYMemento(broom, broom.getBroom().getX(), ny));
355 } else
356 log.warn("Unprocessed event from " + e.getSource());
357 }
358
359 private void syncM2V(final Boolean handle) {
360 if (log.isDebugEnabled())
361 log.debug("handle="
362 + (handle == null ? "-" : handle.booleanValue() ? "out"
363 : "in"));
364 if (handle == null) {
365 in.setEnabled(false);
366 out.setEnabled(false);
367 in.setSelected(false);
368 out.setSelected(false);
369 } else {
370 in.setEnabled(true);
371 out.setEnabled(true);
372 if (handle.booleanValue())
373 out.setSelected(true);
374 else
375 in.setSelected(true);
376 }
377 }
378
379 private void syncM2V(final BoundedRangeModel s) {
380 if (s != null) {
381 if (UseJSpinnerBoundedRange) {
382 split2.setBRM(s);
383 split2.setEnabled(true);
384 } else {
385
386
387 split.setEnabled(true);
388
389
390 final JSpinner.DefaultEditor ed = (JSpinner.DefaultEditor) split
391 .getEditor();
392 ed.getTextField().addFocusListener(this);
393 }
394 } else
395 if (UseJSpinnerBoundedRange)
396 split2.setEnabled(false);
397 else
398 split.setEnabled(false);
399 }
400
401 private void syncM2V(final int idx16) {
402 if (log.isDebugEnabled())
403 log.debug("idx16=" + idx16);
404 if (idx16 < 0) {
405 dark.setSelected(false);
406 light.setSelected(false);
407 rock.setSelectedIndex(-1);
408 dark.setEnabled(false);
409 light.setEnabled(false);
410 rock.setEnabled(false);
411 } else {
412 dark.setEnabled(true);
413 light.setEnabled(true);
414 rock.setEnabled(true);
415 if (RockSet.isDark(idx16))
416 dark.setSelected(true);
417 else
418 light.setSelected(true);
419 rock.setSelectedIndex(RockSet.toIdx8(idx16));
420 }
421 }
422
423 private void syncM2V(final Point2D s) {
424 if (s == null) {
425 x.setValue(0);
426 y.setValue(0);
427 } else {
428 x.setValue(s.getX());
429 y.setValue(s.getY());
430 }
431 x.setEnabled(s != null);
432 y.setEnabled(s != null);
433 }
434
435 private void updateHandle() {
436 if (broom == null)
437 return;
438 final HandleMemento pre = new HandleMemento(broom, broom.getOutTurn());
439 final HandleMemento post;
440 if (in.isSelected())
441 post = new HandleMemento(broom, false);
442 else if (out.isSelected())
443 post = new HandleMemento(broom, true);
444 else
445 post = null;
446 getChanger().undoable(pre, post);
447 }
448
449 private void updateIndex() {
450 if (broom == null)
451 return;
452 if (broom == null)
453 return;
454 final IndexMemento pre = new IndexMemento(broom, broom.getIdx16());
455 final IndexMemento post = new IndexMemento(broom, findIndex());
456 getChanger().undoable(pre, post);
457 }
458 }