1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui.components;
21
22 import com.cosylab.application.state.State;
23 import com.cosylab.gui.components.util.CosyTransferHandler;
24
25 import com.cosylab.util.Debug;
26 import com.cosylab.util.PrintfFormat;
27
28 import java.awt.Color;
29 import java.awt.GridBagConstraints;
30 import java.awt.Insets;
31
32 import java.beans.Beans;
33
34 import javax.swing.JComponent;
35 import javax.swing.JLabel;
36 import javax.swing.TransferHandler;
37
38
39
40
41
42
43
44
45 public abstract class AbstractNumericDisplayerPanel
46 extends AbstractDisplayerPanel
47 {
48 private static final long serialVersionUID = 1L;
49 private Class<? extends Number> numberType = Double.class;
50 private Number max = null;
51 private Number min = null;
52 private PrintfFormat formatter = null;
53 private ResizableTextLabel maxLabel = null;
54 private ResizableTextLabel minLabel = null;
55 private ResizableTextLabel unitsLabel = null;
56 private String format = null;
57 private String units = null;
58 private boolean boundsVisible;
59 private boolean unitsVisible;
60 private boolean unitsShownWithTitle;
61
62
63
64
65 public AbstractNumericDisplayerPanel()
66 {
67 this(null, false, DYNAMIC_LAYOUT, true, true, true, 1,
68 Integer.MAX_VALUE, null, true, false);
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public AbstractNumericDisplayerPanel(String title, boolean titleVisible,
88 int layoutOrientation, boolean resizable, boolean enabled,
89 boolean enchanced, int minTitleFontSize, int maxTitleFontSize,
90 String units, boolean unitsVisible, boolean unitsShownWithTitle)
91 {
92 super(title, titleVisible, layoutOrientation, resizable, enabled,
93 enchanced, minTitleFontSize, maxTitleFontSize);
94
95 formatter = new PrintfFormat("%3.2f");
96
97 max = new Double(Double.POSITIVE_INFINITY);
98 min = new Double(Double.NEGATIVE_INFINITY);
99
100 internalSetFormat();
101 internalSetMaximum();
102 internalSetMinimum();
103
104 setUnits(units);
105 setUnitsVisible(unitsVisible);
106 setUnitsShownWithTitle(unitsShownWithTitle);
107 }
108
109
110
111
112
113
114 public void setBoundsVisible(boolean b)
115 {
116 if (b == boundsVisible) {
117 return;
118 }
119
120 boundsVisible = b;
121 layoutDisplayer();
122 firePropertyChange("boundsVisible", !b, b);
123 }
124
125
126
127
128
129
130
131
132 public boolean isBoundsVisible()
133 {
134 return boundsVisible;
135 }
136
137
138
139
140
141
142 public void setFormat(String value)
143 {
144 if (value == null && format == null
145 || value != null && value.equals(format)) {
146 return;
147 }
148
149 String oldVal = format;
150 format = value;
151 internalSetFormat();
152 layoutDisplayer();
153 firePropertyChange("format", oldVal, getFormat());
154 }
155
156
157
158
159
160
161 public String getFormat()
162 {
163 return format;
164 }
165
166
167
168
169
170
171 public void setLayoutOrientation(int i)
172 {
173 if (isBoundsVisible() && (i != VERTICAL_LAYOUT)) {
174 return;
175 }
176
177 super.setLayoutOrientation(i);
178 }
179
180
181
182
183
184
185 public int getLayoutOrientation()
186 {
187 if (boundsVisible) {
188 return VERTICAL_LAYOUT;
189 }
190
191 return super.getLayoutOrientation();
192 }
193
194
195
196
197
198 public void setState(State state)
199 {
200 super.setState(state);
201
202 setBoundsVisible(state.getBoolean("boundsVisible", isBoundsVisible()));
203 setUnitsVisible(state.getBoolean("unitsVisible", isUnitsVisible()));
204 setUnits(state.getString("units", getUnits()));
205 setFormat(state.getString("format", getFormat()));
206 }
207
208
209
210
211
212 public State getState()
213 {
214 State state = super.getState();
215
216 state.putBoolean("boundsVisible", isBoundsVisible());
217 state.putBoolean("unitsVisible", isUnitsVisible());
218 state.putString("units", getUnits());
219 state.putString("format", getFormat());
220
221 return state;
222 }
223
224
225
226
227
228
229
230 public void setUnits(String value)
231 {
232 if (value == null && units == null
233 || value != null && value.equals(units)) {
234 return;
235 }
236
237 units = value;
238
239 internalSetUnits();
240 layoutDisplayer();
241
242 firePropertyChange("units", null, value);
243 }
244
245
246
247
248
249
250 public String getUnits()
251 {
252 return units;
253 }
254
255
256
257
258
259
260 public void setUnitsVisible(boolean b)
261 {
262 if (b == unitsVisible) {
263 return;
264 }
265
266 unitsVisible = b;
267 layoutDisplayer();
268 firePropertyChange("unitsVisible", !b, b);
269 repaint();
270 }
271
272
273
274
275
276
277 public boolean isUnitsVisible()
278 {
279 return unitsVisible;
280 }
281
282
283
284
285
286
287
288 protected JComponent getMaxComponent()
289 {
290 if (maxLabel == null) {
291 maxLabel = new ResizableTextLabel();
292 maxLabel.setHorizontalAlignment(JLabel.CENTER);
293 maxLabel.addMouseListener(getPopupManager().getMouseHook());
294 maxLabel.setResizable(isResizable());
295 maxLabel.setEnabled(isEnabled());
296 maxLabel.setEnhanced(isEnhanced());
297
298 maxLabel.setMaximumFontSize(getTitleMaximumFontSize());
299 maxLabel.setMinimumFontSize(getTitleMinimumFontSize());
300 maxLabel.setBackground(getBackground());
301 maxLabel.setForeground(getForeground());
302 internalSetMaximum();
303 }
304
305 return maxLabel;
306 }
307
308
309
310
311 protected void setMaximumValue(Number value)
312 {
313 if (value == null) {
314 if (numberType == Double.class) {
315 value = new Double(Double.POSITIVE_INFINITY);
316 }
317
318 if (numberType == Long.class) {
319 value = new Long(Long.MAX_VALUE);
320 }
321 }
322
323 max = value;
324 internalSetMaximum();
325 }
326
327
328
329
330 protected Number getMaximumValue()
331 {
332 return max;
333 }
334
335
336
337
338
339
340
341 protected JComponent getMinComponent()
342 {
343 if (minLabel == null) {
344 minLabel = new ResizableTextLabel();
345 minLabel.setHorizontalAlignment(JLabel.CENTER);
346 minLabel.addMouseListener(getPopupManager().getMouseHook());
347 minLabel.setResizable(isResizable());
348 minLabel.setEnabled(isEnabled());
349 minLabel.setEnhanced(isEnhanced());
350
351 minLabel.setMaximumFontSize(getTitleMaximumFontSize());
352 minLabel.setMinimumFontSize(getTitleMinimumFontSize());
353 minLabel.setBackground(getBackground());
354 minLabel.setForeground(getForeground());
355 internalSetMinimum();
356 }
357
358 return minLabel;
359 }
360
361
362
363
364 protected void setMinimumValue(Number value)
365 {
366 if (value == null) {
367 if (numberType == Double.class) {
368 value = new Double(Double.NEGATIVE_INFINITY);
369 }
370
371 if (numberType == Long.class) {
372 value = new Long(-Long.MAX_VALUE);
373 }
374 }
375
376 min = value;
377 internalSetMinimum();
378 }
379
380
381
382
383 protected Number getMinimumValue()
384 {
385 return min;
386 }
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 protected void setNumberType(Class<? extends Number> class1)
402 {
403 if (class1 == null) {
404 throw new IllegalArgumentException("Number type must not be null.");
405 }
406
407 if (class1 != Double.class && class1 != double.class
408 && class1 != Long.class && class1 != long.class) {
409 throw new IllegalArgumentException(
410 "Class must represent a valid number type.");
411 }
412
413 if (class1 == numberType) {
414 return;
415 }
416
417 if ((class1 == Double.class) || (class1 == double.class)) {
418 numberType = Double.class;
419 min = new Double(min.doubleValue());
420 max = new Double(max.doubleValue());
421 } else if ((class1 == Long.class) || (class1 == long.class)) {
422 numberType = Long.class;
423 min = new Long(min.longValue());
424 max = new Long(max.longValue());
425 } else {
426 throw new IllegalArgumentException("Number type.");
427 }
428
429 if (getFormat() != null) {
430 setFormat(null);
431 }
432 internalSetFormat();
433 }
434
435
436
437
438
439
440
441 protected Class<? extends Number> getNumberType()
442 {
443 return numberType;
444 }
445
446
447
448
449
450
451 protected JComponent getUnitsComponent()
452 {
453 if (unitsLabel == null) {
454 unitsLabel = new ResizableTextLabel();
455 unitsLabel.setHorizontalAlignment(JLabel.LEFT);
456 unitsLabel.addMouseListener(getPopupManager().getMouseHook());
457 unitsLabel.setResizable(isResizable());
458 unitsLabel.setEnhanced(isEnhanced());
459 unitsLabel.setEnabled(isEnabled());
460 unitsLabel.setVisible(isUnitsVisible());
461 unitsLabel.setMaximumFontSize(getTitleMaximumFontSize());
462 unitsLabel.setMinimumFontSize(getTitleMinimumFontSize());
463 unitsLabel.setBackground(getBackground());
464 unitsLabel.setForeground(getForeground());
465 internalSetUnits();
466 }
467
468 return unitsLabel;
469 }
470
471
472
473
474 protected void internalSetEnabled()
475 {
476 super.internalSetEnabled();
477
478 if (maxLabel != null) {
479 maxLabel.setEnabled(isEnabled());
480 }
481
482 if (minLabel != null) {
483 minLabel.setEnabled(isEnabled());
484 }
485
486 if (unitsLabel != null) {
487 unitsLabel.setEnabled(isEnabled());
488 }
489 }
490
491
492
493
494 protected void internalSetEnhanced()
495 {
496 super.internalSetEnhanced();
497
498 if (maxLabel != null) {
499 maxLabel.setEnhanced(isEnhanced());
500 }
501
502 if (minLabel != null) {
503 minLabel.setEnhanced(isEnhanced());
504 }
505
506 if (unitsLabel != null) {
507 unitsLabel.setEnhanced(isEnhanced());
508 }
509 }
510
511 protected void internalSetFormat()
512 {
513 String tFormat = format;
514
515 if (format == null) {
516 tFormat = NumberField.createDefaultFormat(getNumberType());
517 format = tFormat;
518 }
519
520 formatter = new PrintfFormat(tFormat);
521
522 internalSetMaximum();
523 internalSetMinimum();
524 }
525
526 protected void internalSetMaximum()
527 {
528 if (maxLabel != null && formatter != null) {
529 try {
530 maxLabel.setText(formatter.sprintf(getMaximumValue()));
531 } catch (IllegalArgumentException iae) {
532 Debug.out("Bad format '" + format + "': " + iae);
533 }
534 }
535 }
536
537 protected void internalSetMinimum()
538 {
539 if (minLabel != null && formatter != null) {
540 try {
541 minLabel.setText(formatter.sprintf(getMinimumValue()));
542 } catch (IllegalArgumentException iae) {
543 Debug.out("Bad format '" + format + "': " + iae);
544 }
545 }
546 }
547
548
549
550
551
552
553 protected void internalSetResizable()
554 {
555 super.internalSetResizable();
556
557 if (minLabel != null) {
558 minLabel.setResizable(isResizable());
559 }
560
561 if (maxLabel != null) {
562 maxLabel.setResizable(isResizable());
563 }
564
565 if (unitsLabel != null) {
566 unitsLabel.setResizable(isResizable());
567 }
568 }
569
570 protected void internalSetUnits()
571 {
572 if (unitsLabel != null) {
573 String tUnits = units;
574
575 if (units == null && Beans.isDesignTime()) {
576 tUnits = "<u>";
577 }
578
579
580
581
582 unitsLabel.setText(tUnits);
583 }
584 }
585
586
587
588
589
590 protected void internalSetTitle()
591 {
592 super.internalSetTitle();
593
594 String u = units;
595
596 if (unitsShownWithTitle) {
597 if (units == null && Beans.isDesignTime()) {
598 u = "<u>";
599 }
600
601 getTitleComponent().setText(getTitleComponent().getText() + " ["
602 + u + "]");
603 }
604 }
605
606
607
608
609 protected void layoutDisplayer()
610 {
611 if (isUnitsVisible() && isTitleVisible() && isBoundsVisible()
612 && getTitle() != null && getUnits() != null
613 && getTitle().length() > 0 && getUnits().length() > 0) {
614 layoutValueAndTitleAndUnitsAndBounds();
615 } else if (isUnitsVisible() && isBoundsVisible() && getUnits() != null
616 && getUnits().length() > 0) {
617 layoutValueAndUnitsAndBounds();
618 } else if (isUnitsVisible() && isTitleVisible() && getTitle() != null
619 && getUnits() != null && getTitle().length() > 0
620 && getUnits().length() > 0) {
621 layoutValueAndTitleAndUnits();
622 } else if (isUnitsVisible() && getUnits() != null
623 && getUnits().length() > 0) {
624 layoutValueAndUnits();
625 } else if (isBoundsVisible() && isTitleVisible() && getTitle() != null
626 && getTitle().length() > 0) {
627 layoutValueAndTitleAndBounds();
628 } else if (isBoundsVisible()) {
629 layoutValueAndBounds();
630 } else {
631 super.layoutDisplayer();
632 }
633 }
634
635
636
637
638 protected void layoutValueAndBounds()
639 {
640 removeAll();
641
642 Insets insets = (!isResizable()) ? new Insets(2, 2, 2, 2)
643 : new Insets((getSize().height * 3) / 100,
644 (getSize().width * 3) / 100, (getSize().height * 3) / 100,
645 (getSize().width * 3) / 100);
646 int fill = (isResizable() ? GridBagConstraints.BOTH
647 : GridBagConstraints.NONE);
648 double w = isResizable() ? 1.0 : 0.0;
649
650 add(getValueComponent(),
651 new GridBagConstraints(1, 1, 2, 1, w, w * 1.2,
652 GridBagConstraints.CENTER, fill, insets, 0, 0));
653 add(getMinComponent(),
654 new GridBagConstraints(1, 2, 1, 1, w, w * 0.5,
655 GridBagConstraints.CENTER, fill, insets, 0, 0));
656 add(getMaxComponent(),
657 new GridBagConstraints(2, 2, 1, 1, w, w * 0.5,
658 GridBagConstraints.CENTER, fill, insets, 0, 0));
659 }
660
661
662
663
664 protected void layoutValueAndTitleAndBounds()
665 {
666 removeAll();
667
668 Insets insets = (!isResizable()) ? new Insets(2, 2, 2, 2)
669 : new Insets((getSize().height * 3) / 100,
670 (getSize().width * 3) / 100, (getSize().height * 3) / 100,
671 (getSize().width * 3) / 100);
672 int fill = (isResizable() ? GridBagConstraints.BOTH
673 : GridBagConstraints.NONE);
674 double w = isResizable() ? 1.0 : 0.0;
675
676 add(getTitleComponent(),
677 new GridBagConstraints(1, 1, 2, 1, w, w, GridBagConstraints.CENTER,
678 fill, insets, 0, 0));
679 add(getValueComponent(),
680 new GridBagConstraints(1, 2, 2, 1, w, w * 1.2,
681 GridBagConstraints.CENTER, fill, insets, 0, 0));
682 add(getMinComponent(),
683 new GridBagConstraints(1, 3, 1, 1, w, w * 0.5,
684 GridBagConstraints.CENTER, fill, insets, 0, 0));
685 add(getMaxComponent(),
686 new GridBagConstraints(2, 3, 1, 1, w, w * 0.5,
687 GridBagConstraints.CENTER, fill, insets, 0, 0));
688 }
689
690 protected void layoutValueAndTitleAndUnits()
691 {
692 removeAll();
693
694 Insets insets = !isResizable() ? new Insets(2, 2, 2, 2)
695 : new Insets(getSize().height * 3 / 100, getSize().width * 3 / 100,
696 getSize().height * 3 / 100, getSize().width * 3 / 100);
697 int fill = (isResizable() ? GridBagConstraints.BOTH
698 : GridBagConstraints.NONE);
699 double w = isResizable() ? 1.0 : 0.0;
700
701 if (getLayoutOrientation() == HORIZONTAL_LAYOUT
702 || (1. * getSize().height) / (getTitleComponent().getPreferredSize().height
703 + getValueComponent().getPreferredSize().height) < (1. * getSize().width
704 - insets.left - insets.right) / (getTitleComponent()
705 .getPreferredSize().width
706 + getValueComponent().getPreferredSize().width
707 + getUnitsComponent().getPreferredSize().width)
708 && getLayoutOrientation() == DYNAMIC_LAYOUT) {
709 add(getTitleComponent(),
710 new GridBagConstraints(1, 1, 1, 1, w, w,
711 GridBagConstraints.CENTER, fill, insets, 0, 0));
712 add(getValueComponent(),
713 new GridBagConstraints(2, 1, 1, 1, w * 1.2, w,
714 GridBagConstraints.EAST, fill, insets, 0, 0));
715 add(getUnitsComponent(),
716 new GridBagConstraints(3, 1, 1, 1, w * 0.33, w * 0.33,
717 GridBagConstraints.WEST, fill, insets, 0, 0));
718 } else {
719 add(getTitleComponent(),
720 new GridBagConstraints(1, 1, 2, 1, w, w,
721 GridBagConstraints.CENTER, fill, insets, 0, 0));
722 add(getValueComponent(),
723 new GridBagConstraints(1, 2, 1, 1, w * 1.2, w * 1.2,
724 GridBagConstraints.EAST, fill, insets, 0, 0));
725 add(getUnitsComponent(),
726 new GridBagConstraints(2, 2, 1, 1, w * 0.33, w * 0.33,
727 GridBagConstraints.WEST, fill, insets, 0, 0));
728 }
729 }
730
731 protected void layoutValueAndTitleAndUnitsAndBounds()
732 {
733 removeAll();
734
735 Insets insets = !isResizable() ? new Insets(2, 2, 2, 2)
736 : new Insets(getSize().height * 3 / 100, getSize().width * 3 / 100,
737 getSize().height * 3 / 100, getSize().width * 3 / 100);
738 int fill = (isResizable() ? GridBagConstraints.BOTH
739 : GridBagConstraints.NONE);
740 double w = isResizable() ? 1.0 : 0.0;
741
742 add(getTitleComponent(),
743 new GridBagConstraints(1, 1, 2, 1, w, w, GridBagConstraints.CENTER,
744 fill, insets, 0, 0));
745 add(getValueComponent(),
746 new GridBagConstraints(1, 2, 2, 1, w * 1.2, w * 1.2,
747 GridBagConstraints.EAST, fill, insets, 0, 0));
748 add(getUnitsComponent(),
749 new GridBagConstraints(2, 2, 1, 1, w, w, GridBagConstraints.WEST,
750 fill, insets, 0, 0));
751 add(getMinComponent(),
752 new GridBagConstraints(1, 3, 1, 1, w, w * 0.5,
753 GridBagConstraints.CENTER, fill, insets, 0, 0));
754 add(getMaxComponent(),
755 new GridBagConstraints(2, 3, 1, 1, w, w * 0.5,
756 GridBagConstraints.CENTER, fill, insets, 0, 0));
757 }
758
759 protected void layoutValueAndUnits()
760 {
761 removeAll();
762
763 Insets insets = !isResizable() ? new Insets(2, 2, 2, 2)
764 : new Insets(getSize().height * 3 / 100, getSize().width * 3 / 100,
765 getSize().height * 3 / 100, getSize().width * 3 / 100);
766 int fill = (isResizable() ? GridBagConstraints.BOTH
767 : GridBagConstraints.NONE);
768 double w = isResizable() ? 1.0 : 0.0;
769
770 add(getValueComponent(),
771 new GridBagConstraints(1, 1, 1, 1, w * 1.2, w,
772 GridBagConstraints.EAST, fill, insets, 0, 0));
773 add(getUnitsComponent(),
774 new GridBagConstraints(2, 1, 1, 1, w * 0.33, w,
775 GridBagConstraints.WEST, fill, insets, 0, 0));
776 }
777
778 protected void layoutValueAndUnitsAndBounds()
779 {
780 removeAll();
781
782 Insets insets = !isResizable() ? new Insets(2, 2, 2, 2)
783 : new Insets(getSize().height * 3 / 100, getSize().width * 3 / 100,
784 getSize().height * 3 / 100, getSize().width * 3 / 100);
785 int fill = (isResizable() ? GridBagConstraints.BOTH
786 : GridBagConstraints.NONE);
787 double w = isResizable() ? 1.0 : 0.0;
788
789 add(getValueComponent(),
790 new GridBagConstraints(1, 1, 2, 1, w * 1.2, w * 1.2,
791 GridBagConstraints.EAST, fill, insets, 0, 0));
792 add(getUnitsComponent(),
793 new GridBagConstraints(2, 1, 1, 1, w, w * 1.2,
794 GridBagConstraints.WEST, fill, insets, 0, 0));
795 add(getMinComponent(),
796 new GridBagConstraints(1, 2, 1, 1, w, w * 0.5,
797 GridBagConstraints.CENTER, fill, insets, 0, 0));
798 add(getMaxComponent(),
799 new GridBagConstraints(2, 2, 1, 1, w, w * 0.5,
800 GridBagConstraints.CENTER, fill, insets, 0, 0));
801 }
802
803
804
805
806
807
808 public boolean isUnitsShownWithTitle()
809 {
810 return unitsShownWithTitle;
811 }
812
813
814
815
816
817
818
819 public void setUnitsShownWithTitle(boolean unitsShownWithTitle)
820 {
821 if (unitsShownWithTitle == this.unitsShownWithTitle) {
822 return;
823 }
824
825 this.unitsShownWithTitle = unitsShownWithTitle;
826 internalSetTitle();
827 layoutDisplayer();
828 firePropertyChange("unitsShownWithTitle", !unitsShownWithTitle,
829 unitsShownWithTitle);
830 }
831
832
833
834
835 public void setTitleMaximumFontSize(int max) {
836 if (maxLabel!=null) maxLabel.setMaximumFontSize(max);
837 if (minLabel!=null) minLabel.setMaximumFontSize(max);
838 if (unitsLabel!=null) unitsLabel.setMaximumFontSize(max);
839 super.setTitleMaximumFontSize(max);
840 }
841
842
843
844
845 public void setTitleMinimumFontSize(int min) {
846 if (maxLabel!=null) maxLabel.setMinimumFontSize(min);
847 if (minLabel!=null) minLabel.setMinimumFontSize(min);
848 if (unitsLabel!=null) unitsLabel.setMinimumFontSize(min);
849 super.setTitleMinimumFontSize(min);
850 }
851
852
853
854
855 @Override
856 public void setTransferHandler(TransferHandler newHandler) {
857 super.setTransferHandler(newHandler);
858 CosyTransferHandler.registerTransferHandler(this,newHandler,new JComponent[]{getMaxComponent(),getMinComponent(),getUnitsComponent()});
859 }
860
861
862
863
864
865 @Override
866 public void setBackground(Color bg) {
867 super.setBackground(bg);
868 getUnitsComponent().setBackground(bg);
869 getMinComponent().setBackground(bg);
870 getMaxComponent().setBackground(bg);
871 }
872
873
874
875
876
877 @Override
878 public void setForeground(Color fg) {
879 super.setForeground(fg);
880 getUnitsComponent().setForeground(fg);
881 getMinComponent().setForeground(fg);
882 getMaxComponent().setForeground(fg);
883 }
884 }
885
886