1 package com.cosylab.gui;
2
3 import java.awt.Component;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.awt.event.MouseAdapter;
7 import java.awt.event.MouseEvent;
8 import java.beans.Beans;
9 import java.beans.PropertyVetoException;
10 import java.util.Map;
11
12 import javax.swing.AbstractAction;
13 import javax.swing.JCheckBox;
14 import javax.swing.JDialog;
15
16 import com.cosylab.gui.adapters.Converter;
17 import com.cosylab.gui.components.customizer.AbstractCustomizerPanel;
18 import com.cosylab.gui.components.util.PopupManager;
19 import com.cosylab.gui.displayers.ConvertibleDisplayer;
20 import com.cosylab.gui.displayers.DataConsumer;
21 import com.cosylab.gui.displayers.DataSource;
22 import com.cosylab.gui.displayers.DataSourceSupport;
23 import com.cosylab.gui.displayers.DataState;
24 import com.cosylab.gui.displayers.DisplayerUtilities;
25 import com.cosylab.gui.displayers.DoubleConsumer;
26 import com.cosylab.gui.displayers.DoubleConsumerMulticaster;
27 import com.cosylab.gui.displayers.DoubleDisplayer;
28 import com.cosylab.gui.displayers.NonblockingNumberConsumer;
29 import com.cosylab.util.CommonException;
30
31
32
33
34
35
36
37
38 public class CheckBoxController extends JCheckBox implements DoubleDisplayer, DataSource, ConvertibleDisplayer {
39
40 private static final long serialVersionUID = -84774768633096095L;
41
42 public static final String SELECTED_VALUE = "selectedValue";
43
44 public static final String DESELECTED_VALUE = "deselectedValue";
45
46 protected static final String DEFAULT_TEXT = "Enable";
47
48 private String title;
49 private DataSource dataSource;
50 private DataState dataState = new DataState(DataState.UNDEFINED);
51 private int suspendCount = 0;
52 private PopupManager popupManager;
53 private InfoDialog infoDialog;
54 private AbstractCustomizerPanel customizer;
55 @SuppressWarnings("unchecked")
56 private DataSourceSupport support = new DataSourceSupport(new Class[]{
57 NonblockingNumberConsumer.class
58 });
59 private Converter converter;
60
61 private Number selectedValue = 1;
62
63 private Number deselectedValue = 0;
64
65 private boolean popupEnabled = false;
66
67 private double minimum;
68
69 private double maximum;
70
71 private String units;
72
73 private double value;
74
75 private String format;
76
77
78
79
80 private class CheckBoxListener implements ActionListener {
81
82 public void actionPerformed(ActionEvent e) {
83 DataConsumer[] d = getConsumers();
84 boolean sel = isSelected();
85
86 for (int i = 0; i < d.length; i++) {
87 NonblockingNumberConsumer dd = (NonblockingNumberConsumer)d[i];
88
89 if (dd != null) {
90 if (sel) dd.updateNonblocking(selectedValue);
91 else dd.updateNonblocking(deselectedValue);
92 }
93 }
94
95 }
96
97 }
98
99
100
101
102
103 public CheckBoxController() {
104 this(DEFAULT_TEXT);
105 }
106
107
108
109
110
111
112 public CheckBoxController(String text) {
113 setText(text);
114 initialize();
115 }
116
117 protected void initialize(){
118 this.addActionListener(new CheckBoxListener());
119
120 addMouseMotionListener(new MouseAdapter() {
121 public void mouseDragged(MouseEvent e) {
122
123 processMouseEvent(new MouseEvent((Component)e.getSource(), MouseEvent.MOUSE_EXITED, e.getWhen(),
124 e.getModifiers(), e.getX(), e.getY(), e.getClickCount(), false));
125 }
126 });
127
128 setPopupEnabled(true);
129 }
130
131
132
133
134 public void setSelectedValue(Number value){
135 if (selectedValue == value) return;
136
137 Number old = selectedValue;
138 selectedValue = value;
139
140 firePropertyChange(SELECTED_VALUE,old,selectedValue);
141 }
142
143
144
145
146 public Number getSelectedValue(){
147 return selectedValue;
148 }
149
150
151
152
153 public void setDeselectedValue(Number value){
154 if (deselectedValue == value) return;
155
156 Number old = deselectedValue;
157 deselectedValue = value;
158
159 firePropertyChange(DESELECTED_VALUE,old,deselectedValue);
160 }
161
162
163
164
165 public Number getDeselectedValue(){
166 return deselectedValue;
167 }
168
169
170
171
172
173 public String getFormat() {
174 return format;
175 }
176
177
178
179
180
181 public double getMaximum() {
182 return maximum;
183 }
184
185
186
187
188
189 public double getMinimum() {
190 return minimum;
191 }
192
193
194
195
196
197 public String getUnits() {
198 return units;
199 }
200
201
202
203
204
205 public double getValue() {
206 return value;
207 }
208
209
210
211
212
213 public void setFormat(String value) {
214 if (format == null) {
215 if (value == null) return;
216 } else if (format.equals(value)) return;
217
218 String oldValue = format;
219 format = value;
220
221 firePropertyChange("format", oldValue, format);
222 }
223
224
225
226
227
228 public void setMaximum(double value) {
229 if (value == maximum) return;
230
231 double oldValue = maximum;
232 maximum = value;
233
234 firePropertyChange("maximum", oldValue, maximum);
235 }
236
237
238
239
240
241 public void setMinimum(double value) {
242 if (value == minimum) return;
243
244 double oldValue = minimum;
245 minimum = value;
246
247 firePropertyChange("minimum", oldValue, minimum);
248 }
249
250
251
252
253
254 public void setUnits(String value) {
255 if (units == null) {
256 if (value == null) return;
257 } else if (units.equals(value)) return;
258
259 String oldValue = units;
260 units = value;
261
262 firePropertyChange("units", oldValue, units);
263 }
264
265
266
267
268
269 public void setValue(double val) {
270 if (val == value) return;
271
272 double oldValue = value;
273 value = val;
274
275 firePropertyChange("value", oldValue, value);
276 }
277
278
279
280
281
282 public DataSource getDataSource() {
283 return dataSource;
284 }
285
286
287
288
289
290 public String getTitle() {
291 return title;
292 }
293
294
295
296
297
298 public boolean isEditable() {
299 return true;
300 }
301
302
303
304
305
306 public void setDataSource(DataSource dataSource)
307 throws PropertyVetoException {
308 DisplayerUtilities.prepareNewDataSource(dataSource,this);
309
310 DataSource old= this.dataSource;
311 this.dataSource = dataSource;
312
313 firePropertyChange(DATA_SOURCE,old,dataSource);
314 }
315
316 protected void internalSetTitle()
317 {
318 String value = title;
319
320 if (value == null && Beans.isDesignTime()) {
321 value = "<title>";
322 }
323 }
324
325
326
327
328
329 public void setTitle(String value) {
330 String oldVal = title;
331 title = value;
332 internalSetTitle();
333 firePropertyChange("title", oldVal, value);
334 }
335
336
337
338
339
340 @SuppressWarnings("unchecked")
341 public DataConsumer getDataConsumer(Class type) {
342 if (type == DoubleConsumer.class) {
343 return this;
344 }
345
346 return DoubleConsumerMulticaster.createDataConsumer(type, this);
347 }
348
349
350
351
352
353 public DataConsumer getDefaultDataConsumer() {
354 return this;
355 }
356
357
358
359
360
361 public String[] getSupportedCharacteristics() {
362 return DisplayerUtilities.COMMON_NUMERIC_DISPLAYER_CHARACTERISTICS;
363 }
364
365
366
367
368
369 @SuppressWarnings("unchecked")
370 public Class<DataConsumer>[] getSupportedConsumerTypes() {
371 return DoubleConsumerMulticaster.PREFERED_CONSUMER_TYPES;
372 }
373
374
375
376
377
378 @SuppressWarnings("unchecked")
379 public void setCharacteristics(Map characteristics) {
380 if (characteristics == null) {
381 throw new NullPointerException("characteristics");
382 }
383
384 DisplayerUtilities.setCharacteristics(characteristics, this);
385 }
386
387
388
389
390
391 public void updateDataState(DataState state) {
392 DataState old = dataState;
393 dataState = state;
394 firePropertyChange(DATA_STATE, old, dataState);
395 }
396
397 private void internalCleanup() {
398 setText(DEFAULT_TEXT);
399 setTitle(null);
400 setSelected(false);
401 }
402
403
404
405
406
407 public void cleanup() {
408 internalCleanup();
409 updateDataState(new DataState(DataState.NOT_INITIALIZED));
410 }
411
412
413
414
415
416 public boolean isSuspended() {
417 return suspendCount > 0;
418 }
419
420
421
422
423
424 public void resume() {
425 if (suspendCount > 0) {
426 suspendCount--;
427 }
428
429 if (suspendCount == 0) {
430 setEnabled(true);
431 }
432 }
433
434
435
436
437
438 public void suspend() {
439 setEnabled(false);
440 suspendCount++;
441 }
442
443
444
445
446
447 public PopupManager getPopupManager() {
448 if (popupManager == null) {
449 popupManager = new PopupManager(this, false);
450 popupManager.addAction(new AbstractAction("Preferences...") {
451 private static final long serialVersionUID = 1L;
452 public void actionPerformed(ActionEvent e)
453 {
454 getCustomizer().showDialog();
455 }
456 });
457
458 popupManager.addAction(new AbstractAction("Info...") {
459 private static final long serialVersionUID = 1L;
460
461 public void actionPerformed(ActionEvent e)
462 {
463 getInfoDialog().setVisible(true);
464 }
465 });
466 }
467
468 return popupManager;
469 }
470
471
472
473
474
475
476 public boolean isPopupEnabled() {
477 return popupEnabled;
478 }
479
480
481
482
483
484
485 public void setPopupEnabled(boolean enabled) {
486 if (popupEnabled == enabled) return;
487 popupEnabled = enabled;
488 if (enabled) {
489 addMouseListener(getPopupManager().getMouseHook());
490 } else {
491 removeMouseListener(getPopupManager().getMouseHook());
492 }
493 firePropertyChange("popupEnabled",!popupEnabled,popupEnabled);
494 }
495
496 protected JDialog getInfoDialog() {
497 if (infoDialog == null) {
498 infoDialog = new InfoDialog(this);
499 }
500 return infoDialog;
501 }
502
503 protected AbstractCustomizerPanel getCustomizer() {
504 if (customizer == null) {
505 customizer = AbstractCustomizerPanel.findCustomizer(this);
506 }
507 return customizer;
508 }
509
510
511
512
513
514 public DataState getDataState() {
515 return dataState;
516 }
517
518
519
520
521
522 public void updateValue(long timestamp, double value)
523 throws CommonException {
524 if (value == selectedValue.doubleValue()) {
525 setSelected(true);
526 updateDataState(new DataState(DataState.NORMAL));
527 }
528 else if (value == deselectedValue.doubleValue()){
529 setSelected(false);
530 updateDataState(new DataState(DataState.NORMAL));
531 }
532 else {
533 updateDataState(new DataState(DataState.WARNING));
534 }
535 }
536
537
538
539
540
541
542
543
544 public void addConsumer(DataConsumer consumer) throws PropertyVetoException {
545 if (consumer == null) {
546 throw new NullPointerException("consumer");
547 }
548
549 NonblockingNumberConsumer c = (NonblockingNumberConsumer)consumer
550 .getDataConsumer(NonblockingNumberConsumer.class);
551
552 if (c == null) {
553 throw new PropertyVetoException("Consumer '" + consumer
554 + "' must support NonblockingNumberConsumer.", null);
555 }
556
557 support.addConsumer(c);
558 }
559
560
561
562
563
564 public Class<DataConsumer>[] getAcceptableConsumerTypes() {
565 return support.getAcceptableConsumerTypes();
566 }
567
568
569
570
571
572 public DataConsumer[] getConsumers() {
573 return support.getConsumers();
574 }
575
576
577
578
579
580 public void removeAllConsumers() {
581 support.removeAllConsumers();
582 }
583
584
585
586
587
588 public void removeConsumer(DataConsumer consumer) {
589 support.removeConsumer(consumer);
590 }
591
592
593
594
595
596 public Converter getConverter() {
597 return converter;
598 }
599
600
601
602
603
604 public void setConverter(Converter converter) throws PropertyVetoException {
605 if (this.converter != null && this.converter.equals(converter) ||
606 (this.converter == null && converter == null)) return;
607 DisplayerUtilities.prepareNewConverter(converter,this);
608
609 Converter old= this.converter;
610 this.converter = converter;
611
612 firePropertyChange(CONVERTER_PROPERTY,old,this.converter);
613 }
614
615 }