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.events.SetEvent;
23 import com.cosylab.events.SetListener;
24
25 import com.cosylab.gui.components.util.ColorHelper;
26 import com.cosylab.gui.components.util.PopupManageable;
27 import com.cosylab.gui.components.util.PopupManager;
28 import com.cosylab.gui.components.util.ScreenCapturer;
29 import com.cosylab.gui.components.wheelswitch.AbstractWheelswitchFormatter;
30 import com.cosylab.gui.components.wheelswitch.Digit;
31 import com.cosylab.gui.components.wheelswitch.StaticDigit;
32 import com.cosylab.gui.components.wheelswitch.UpDownButton;
33 import com.cosylab.gui.components.wheelswitch.ValueDigit;
34 import com.cosylab.gui.components.wheelswitch.WheelswitchFormatter;
35 import com.cosylab.gui.components.wheelswitch.WheelswitchLayout;
36
37 import com.cosylab.util.Debug;
38
39 import java.awt.BorderLayout;
40 import java.awt.Color;
41 import java.awt.Dimension;
42 import java.awt.event.ActionEvent;
43 import java.awt.event.ActionListener;
44 import java.awt.event.KeyAdapter;
45 import java.awt.event.KeyEvent;
46 import java.awt.event.MouseAdapter;
47 import java.awt.event.MouseEvent;
48 import java.awt.event.MouseWheelEvent;
49 import java.awt.event.MouseWheelListener;
50
51 import java.util.ArrayList;
52 import java.util.Timer;
53 import java.util.TimerTask;
54
55 import javax.swing.AbstractAction;
56 import javax.swing.Box;
57 import javax.swing.JButton;
58 import javax.swing.JFrame;
59 import javax.swing.JPanel;
60 import javax.swing.SwingUtilities;
61 import javax.swing.event.EventListenerList;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public class Wheelswitch extends JPanel implements PopupManageable
78 {
79 private static final long serialVersionUID = 1L;
80
81
82
83
84
85
86
87
88 protected class KeyHandler extends KeyAdapter
89 {
90
91
92
93
94
95 public void keyPressed(KeyEvent e)
96 {
97 if (editable && isEnabled()) {
98 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
99
100 setSelectedDigit(-1);
101 e.consume();
102 return;
103 }
104 int i = getSelectedDigit();
105
106 if (i >= 0) {
107 if ((e.getKeyChar() >= '0') && (e.getKeyChar() <= '9')) {
108 setDigitValue(i,
109 Integer.parseInt(String.valueOf(e.getKeyChar())));
110 setSelectedDigit(INCREASE_SELECTION);
111 } else if (e.getKeyCode() == KeyEvent.VK_UP) {
112 setDigitValue(i, ValueDigit.INCREASE_VALUE);
113 } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
114 setDigitValue(i, ValueDigit.DECREASE_VALUE);
115 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
116 setSelectedDigit(INCREASE_SELECTION);
117 } else if ((e.getKeyCode() == KeyEvent.VK_LEFT)
118 || (e.getKeyCode() == KeyEvent.VK_BACK_SPACE)) {
119 setSelectedDigit(DECREASE_SELECTION);
120 }
121 } else {
122 setSelectedDigit(0);
123 }
124 }
125 }
126 }
127
128
129
130
131
132
133
134
135 protected class MouseHandler extends MouseAdapter
136 {
137
138
139
140
141
142
143 public void mousePressed(MouseEvent e)
144 {
145 if (e.getButton() == MouseEvent.BUTTON1) {
146 int index = digits.indexOf(e.getSource());
147
148 if (getSelectedDigit() == index) {
149 setSelectedDigit(-1);
150 } else {
151 setSelectedDigit(index);
152 }
153 requestFocusInWindow();
154 }
155 }
156 }
157
158
159
160
161
162
163
164
165 protected class WheelSwitchMouseHandler extends MouseAdapter implements MouseWheelListener
166 {
167
168
169
170
171
172 public void mouseWheelMoved(MouseWheelEvent e)
173 {
174 Debug.out("mousewheel");
175
176 if (editable && isEnabled()) {
177 int i = getSelectedDigit();
178
179 if (i >= 0) {
180 if (e.getWheelRotation() > 0) {
181 setDigitValue(i, ValueDigit.DECREASE_VALUE);
182 } else {
183 setDigitValue(i, ValueDigit.INCREASE_VALUE);
184 }
185 }
186 }
187 }
188
189
190 @Override
191 public void mousePressed(MouseEvent e) {
192 requestFocus();
193 if (getSelectedDigit() == -1) {
194 if (SwingUtilities.isLeftMouseButton(e)) {
195 if (selectedDigit < 0) {
196 setSelectedDigit(0);
197 }
198 } else if (SwingUtilities.isRightMouseButton(e)) {
199 if (selectedDigit < 0) {
200 setSelectedDigit(digits.size()-1);
201 }
202
203 }
204 }
205 }
206 }
207
208
209
210
211
212
213
214
215 protected class TiltHandler extends Timer
216 {
217 private class TiltTask extends TimerTask
218 {
219 public void run()
220 {
221 if (numberOfTilts >= MAX_NUMBER_OF_TILTS) {
222 cancel();
223
224 for (int i = 0; i < digits.size(); i++) {
225 (digits.get(i)).setTilting(false);
226 }
227 } else {
228 numberOfTilts++;
229
230 for (int i = 0; i < digits.size(); i++) {
231 (digits.get(i)).setTilting(!(digits.get(i))
232 .isTilting());
233 }
234 }
235
236 repaint();
237 }
238 }
239
240
241
242 private final int MAX_NUMBER_OF_TILTS = 3;
243 private final long TILT_RATE = 200;
244 private int numberOfTilts = MAX_NUMBER_OF_TILTS;
245
246
247
248
249
250 public void tilt()
251 {
252 if ((formatter.getValue() < formatter.getMaximum())
253 && (formatter.getValue() > formatter.getMinimum())
254 || !tiltingEnabled) {
255
256
257
258
259
260 return;
261 }
262
263
264
265
266
267
268 if (numberOfTilts >= MAX_NUMBER_OF_TILTS) {
269 numberOfTilts = 0;
270 schedule(new TiltTask(), 0, TILT_RATE);
271 } else {
272 numberOfTilts = 0;
273 }
274 }
275 }
276
277
278
279
280
281
282
283
284 protected class UpDownActionHandler implements ActionListener
285 {
286
287
288
289
290
291 public void actionPerformed(ActionEvent e)
292 {
293 if (editable && isEnabled()) {
294 int i = getSelectedDigit();
295
296 if (i >= 0) {
297 int value = 0;
298
299 if (e.getSource() == getUpDownButton().getUpButton()) {
300 value = ValueDigit.INCREASE_VALUE;
301 }
302
303 if (e.getSource() == getUpDownButton().getDownButton()) {
304 value = ValueDigit.DECREASE_VALUE;
305 }
306
307 setDigitValue(i, value);
308 } else {
309
310
311
312
313
314 setSelectedDigit(0);
315 }
316
317
318 }
319 }
320 }
321
322 protected static int INCREASE_SELECTION = -11;
323 protected static int DECREASE_SELECTION = -12;
324
325
326 public static final String VALUE = "value";
327
328
329 public static final String EDITABLE = "editable";
330 protected EventListenerList listenerList = null;
331 protected KeyHandler keyHandler;
332 protected MouseHandler mouseHandler;
333 protected TiltHandler tiltHandler;
334 protected WheelSwitchMouseHandler handler;
335 private Dimension minimumSize = null;
336 private Dimension preferredSize = null;
337 private java.util.List<Digit> digits;
338 private java.util.List<Digit> unitDigits;
339 private java.util.List<Digit> hiddenDigits;
340 private UpDownButton upDownButton;
341 private AbstractWheelswitchFormatter formatter;
342 private boolean editable = true;
343 private PopupManager popupManager;
344 private boolean popupEnabled;
345 private boolean enhanced = true;
346 private boolean animated = false;
347 private boolean tiltingEnabled;
348 private int selectedDigit = -1;
349 private ResizableTextLabel unitLabel;
350 private boolean debug = false;
351 private boolean unitSeparate = false;
352 private boolean digitsTakeUpAllSpace = true;
353 private int numberOfAllDigits = 10;
354
355
356
357
358 public static final String HORIZONTAL_ALIGNMENT = "horizontalAlignment";
359
360
361
362
363
364
365
366
367
368
369 public Wheelswitch(String newFormat, double newValue, String newUnit)
370 {
371 super();
372 listenerList = new EventListenerList();
373 mouseHandler = new MouseHandler();
374 keyHandler = new KeyHandler();
375 tiltHandler = new TiltHandler();
376 handler = new WheelSwitchMouseHandler();
377
378 digits = new ArrayList<Digit>();
379 unitDigits = new ArrayList<Digit>();
380 hiddenDigits = new ArrayList<Digit>();
381
382
383 this.formatter = new WheelswitchFormatter(newFormat);
384 this.formatter.setUnit(newUnit);
385 this.formatter.setValue(newValue);
386
387 addKeyListener(keyHandler);
388 addMouseWheelListener(handler);
389 getUpDownButton().addMouseListener(handler);
390 addMouseListener(handler);
391
392 setFocusable(true);
393 setBackground(ColorHelper.getCosyControl());
394 setLayout(new WheelswitchLayout());
395
396 setupValueDigits();
397 setupUnitDigits();
398 setupLayout();
399 validate();
400 repaint();
401 setPopupEnabled(true);
402 }
403
404 private UpDownButton getUpDownButton() {
405 if (upDownButton == null) {
406 upDownButton = new UpDownButton();
407 upDownButton.setName("upDownButton");
408 upDownButton.getUpButton().addActionListener(new UpDownActionHandler());
409 upDownButton.getDownButton().addActionListener(new UpDownActionHandler());
410 upDownButton.addKeyListener(keyHandler);
411 upDownButton.setEnabled(false);
412 }
413 return upDownButton;
414 }
415
416 private ResizableTextLabel getUnitLabel() {
417 if (unitLabel == null) {
418 unitLabel = new ResizableTextLabel();
419 unitLabel.setResizable(true);
420 unitLabel.setEnhanced(enhanced);
421 }
422
423 return unitLabel;
424 }
425
426
427
428
429
430 public PopupManager getPopupManager()
431 {
432 if (popupManager == null) {
433 popupManager = new PopupManager(this, false);
434 popupManager.addAction(new AbstractAction("Capture screen...") {
435 private static final long serialVersionUID = 1L;
436
437 public void actionPerformed(ActionEvent e)
438 {
439 ScreenCapturer sc = new ScreenCapturer(Wheelswitch.this);
440 sc.showScreenDialog();
441 }
442 });
443 }
444
445 return popupManager;
446 }
447
448
449
450
451
452
453 public boolean isPopupEnabled() {
454 return popupEnabled;
455 }
456
457
458
459
460
461
462 public void setPopupEnabled(boolean enabled) {
463 if (popupEnabled == enabled) return;
464 popupEnabled = enabled;
465 if (enabled) {
466 addMouseListener(getPopupManager().getMouseHook());
467 } else {
468 removeMouseListener(getPopupManager().getMouseHook());
469 }
470 firePropertyChange("popupEnabled",!popupEnabled,popupEnabled);
471 }
472
473
474
475
476
477
478
479
480
481 public Wheelswitch(double newValue)
482 {
483 this(null, newValue, null);
484 }
485
486
487
488
489
490
491
492 public Wheelswitch()
493 {
494 this(null, 0, null);
495 }
496
497
498
499
500
501
502
503 public void setEditable(boolean newEditable)
504 {
505 if (newEditable == editable) {
506 return;
507 }
508
509 boolean oldEditable = editable;
510 editable = newEditable;
511 firePropertyChange(EDITABLE, oldEditable, newEditable);
512
513 if (!isEnabled()) {
514 return;
515 }
516
517 setupLayout();
518 validate();
519 repaint();
520 }
521
522
523
524
525
526
527 public boolean isEditable()
528 {
529 return editable;
530 }
531
532
533
534
535
536
537
538 public void setEnhanced(boolean enhanced)
539 {
540 if (this.enhanced == enhanced) {
541 return;
542 }
543
544 firePropertyChange("enhanced", this.enhanced, enhanced);
545 this.enhanced = enhanced;
546
547 for (int i = 0; i < digits.size(); i++) {
548 (digits.get(i)).setEnhanced(enhanced);
549 }
550
551 for (int i = 0; i < unitDigits.size(); i++) {
552 (unitDigits.get(i)).setEnhanced(enhanced);
553 }
554
555 getUnitLabel().setEnhanced(enhanced);
556 }
557
558
559
560
561
562
563 public boolean isEnhanced()
564 {
565 return enhanced;
566 }
567
568
569
570
571
572
573
574
575
576
577
578 public void setFormat(String newFormat)
579 {
580 if (newFormat == null) {
581 throw new NullPointerException("newFormat");
582 }
583
584 if ((formatter.getFormat() != null)
585 && formatter.getFormat().equals(newFormat)) {
586 return;
587 }
588
589 String oldFormat = formatter.getFormat();
590
591 try {
592 formatter.setFormat(newFormat);
593 } catch (IllegalArgumentException e) {
594 Debug.out(e);
595
596 return;
597 }
598
599 firePropertyChange("format", oldFormat, newFormat);
600
601 if (!isEnabled()) {
602 return;
603 }
604
605 setupValueDigits();
606 setupLayout();
607 validate();
608 repaint();
609 }
610
611
612
613
614
615
616
617
618 public String getFormat()
619 {
620 return formatter.getFormat();
621 }
622
623
624
625
626
627
628
629
630 public void setGraphMax(double newValue)
631 {
632 double oldValue = formatter.getMaximum();
633
634 if (oldValue == newValue) {
635 return;
636 }
637
638 formatter.setMaximum(newValue);
639
640 firePropertyChange("graphMax", oldValue, newValue);
641
642 checkBounds();
643 }
644
645
646
647
648
649
650
651
652 public double getGraphMax()
653 {
654 return formatter.getMaximum();
655 }
656
657
658
659
660
661
662
663
664 public void setGraphMin(double newValue)
665 {
666 double oldValue = formatter.getMinimum();
667
668 if (oldValue == newValue) {
669 return;
670 }
671
672 formatter.setMinimum(newValue);
673
674 firePropertyChange("graphMin", oldValue, newValue);
675
676 checkBounds();
677 }
678
679
680
681
682
683
684
685
686 public double getGraphMin()
687 {
688 return formatter.getMinimum();
689 }
690
691
692
693
694
695
696
697
698 public void setMaxMin(double max, double min)
699 {
700 setGraphMax(max);
701 setGraphMin(min);
702 }
703
704
705
706
707
708 public Dimension getMinimumSize()
709 {
710 if (minimumSize == null) {
711 int height = 0;
712 int width = 0;
713
714 for (int i = 0; i < getComponentCount(); i++) {
715 width += getComponent(i).getMinimumSize().width;
716 height = Math.max(height,
717 getComponent(i).getMinimumSize().height);
718 }
719
720 minimumSize = new Dimension(width, height);
721 }
722
723 return minimumSize;
724 }
725
726
727
728
729
730 public Dimension getPreferredSize()
731 {
732 if (preferredSize == null) {
733 int height = 0;
734 int width = 0;
735
736 for (int i = 0; i < getComponentCount(); i++) {
737 width += getComponent(i).getPreferredSize().width;
738 height = Math.max(height,
739 getComponent(i).getPreferredSize().height);
740 }
741
742 preferredSize = new Dimension(width, height);
743 }
744
745 return preferredSize;
746 }
747
748
749
750
751
752
753
754 public void setTiltingEnabled(boolean b)
755 {
756 if (tiltingEnabled == b) {
757 return;
758 }
759
760 tiltingEnabled = b;
761 firePropertyChange("tiltingEnabled", !b, b);
762 }
763
764
765
766
767
768
769
770 public boolean isTiltingEnabled()
771 {
772 return tiltingEnabled;
773 }
774
775
776
777
778
779
780
781
782 public void setUnit(String newUnit)
783 {
784 String oldUnit = formatter.getUnit();
785
786 if (oldUnit == newUnit) {
787 return;
788 }
789
790 formatter.setUnit(newUnit);
791 firePropertyChange("unit", oldUnit, newUnit);
792
793 if (!isEnabled()) {
794 return;
795 }
796
797 setupUnitDigits();
798 setupLayout();
799 doLayout();
800 repaint();
801 }
802
803
804
805
806
807
808
809
810 public String getUnit()
811 {
812 return formatter.getUnit();
813 }
814
815
816
817
818
819
820
821
822
823
824 public void setValue(double newValue)
825 {
826 double oldValue = formatter.getValue();
827
828 if (oldValue == newValue) {
829 return;
830 }
831
832 firePropertyChange(VALUE, oldValue, newValue);
833
834 int oldDigitSelection = getSelectedDigit();
835 int decimalSelection = parseDecimalPosition(oldDigitSelection);
836
837 String oldStringValue = formatter.getString();
838 formatter.setValue(newValue);
839
840 String newStringValue = formatter.getString();
841
842 if (!isEnabled()) {
843 return;
844 }
845
846 process(oldStringValue, newStringValue);
847
848 int newDigitSelection = parseDigitPosition(decimalSelection);
849
850 if ((newDigitSelection < digits.size()) && (newDigitSelection >= 0)) {
851 setSelectedDigit(newDigitSelection);
852 } else {
853 setSelectedDigit(-1);
854 }
855
856 checkBounds();
857
858
859 }
860
861 private void checkBounds()
862 {
863 if (getValue() > getGraphMax()) {
864 getUpDownButton().setOutOfBounds(1);
865 } else if (getValue() < getGraphMin()) {
866 getUpDownButton().setOutOfBounds(-1);
867 } else {
868 getUpDownButton().setOutOfBounds(0);
869 }
870 }
871
872
873
874
875
876
877
878
879
880 public double getValue()
881 {
882 return formatter.getValue();
883 }
884
885
886
887
888
889
890
891
892
893
894
895 public void addSetListener(SetListener l)
896 {
897 listenerList.add(SetListener.class, l);
898 }
899
900
901
902
903
904 public void setEnabled(boolean arg0)
905 {
906 super.setEnabled(arg0);
907
908 setupValueDigits();
909 setupUnitDigits();
910 setupLayout();
911 validate();
912 repaint();
913
914 for (int i = 0; i < digits.size(); i++) {
915 (digits.get(i)).setEnabled(arg0);
916 }
917
918 for (int i = 0; i < unitDigits.size(); i++) {
919 (unitDigits.get(i)).setEnabled(arg0);
920 }
921
922 getUpDownButton().setEnabled(arg0);
923 }
924
925
926
927
928
929
930
931 public void setMaximumDigits(int bound)
932 {
933 int oldBound = formatter.getMaximumDigits();
934 formatter.setMaximumDigits(bound);
935 firePropertyChange("maximumDigits", oldBound, bound);
936 }
937
938
939
940
941
942
943
944
945 public void removeSetListener(SetListener l)
946 {
947 listenerList.remove(SetListener.class, l);
948 }
949
950
951
952
953 protected void setDigitValue(int i, int newValue)
954 {
955 if (digits.get(i) instanceof StaticDigit) {
956 return;
957 }
958
959 String oldStringValue = formatter.getString();
960 String newStringValue = oldStringValue;
961
962
963 if ((newValue == ValueDigit.INCREASE_VALUE)
964 || (newValue == ValueDigit.DECREASE_VALUE)) {
965 int expIndex = oldStringValue.indexOf('E');
966
967 if (expIndex == -1) {
968 expIndex = oldStringValue.length();
969 }
970
971 if (((oldStringValue.charAt(0) == '-') && (i < expIndex))
972 ^ ((i > expIndex) && (expIndex < (oldStringValue.length() - 1))
973 && (oldStringValue.charAt(expIndex + 1) == '-'))) {
974 if (newValue == ValueDigit.INCREASE_VALUE) {
975 newValue = ValueDigit.DECREASE_VALUE;
976 } else {
977 newValue = ValueDigit.INCREASE_VALUE;
978 }
979 }
980 }
981
982 if ((newValue >= 0) && (newValue <= 9)) {
983 newStringValue = oldStringValue.substring(0, i)
984 + String.valueOf(newValue) + oldStringValue.substring(i + 1);
985 } else if (newValue == ValueDigit.INCREASE_VALUE) {
986 int j;
987
988 for (j = i;
989 ((j >= 0) && (oldStringValue.charAt(j) != 'E')
990 && (oldStringValue.charAt(j) != '+')
991 && (oldStringValue.charAt(j) != '-') && (newValue != 0));
992 j--) {
993 if (oldStringValue.charAt(j) == '.') {
994 continue;
995 } else if (oldStringValue.charAt(j) != '9') {
996 newStringValue = newStringValue.substring(0, j)
997 + String.valueOf(Integer.parseInt(
998 newStringValue.substring(j, j + 1)) + 1)
999 + newStringValue.substring(j + 1);
1000 newValue = 0;
1001 } else {
1002
1003 newStringValue = newStringValue.substring(0, j) + "0"
1004 + newStringValue.substring(j + 1);
1005 }
1006 }
1007
1008 if (newValue != 0) {
1009 if (oldStringValue.charAt(0) == '.') {
1010 newStringValue = "1" + newStringValue;
1011 } else if ((oldStringValue.charAt(j + 1) == '.')
1012 && ((oldStringValue.charAt(j) == '+')
1013 || (oldStringValue.charAt(j) == '-')
1014 || (oldStringValue.charAt(j) == 'E'))) {
1015 newStringValue = newStringValue.substring(0, 1) + "1"
1016 + newStringValue.substring(1);
1017 } else {
1018 newStringValue = newStringValue.substring(0, j + 1) + "10"
1019 + newStringValue.substring(j + 2);
1020 }
1021 }
1022 } else if (newValue == ValueDigit.DECREASE_VALUE) {
1023 boolean signTag = false;
1024
1025 for (int j = i;
1026 ((j >= 0) && (oldStringValue.charAt(j) != 'E')
1027 && (oldStringValue.charAt(j) != '+')
1028 && (oldStringValue.charAt(j) != '-')); j--) {
1029 if ((oldStringValue.charAt(j) != '.')
1030 && (oldStringValue.charAt(j) != '0')) {
1031 signTag = true;
1032 }
1033 }
1034
1035 if (signTag) {
1036 for (int j = i;
1037 ((j >= 0) && (oldStringValue.charAt(j) != 'E')
1038 && (oldStringValue.charAt(j) != '+')
1039 && (oldStringValue.charAt(j) != '-') && (newValue != 0));
1040 j--) {
1041 if (oldStringValue.charAt(j) == '.') {
1042
1043 } else if (oldStringValue.charAt(j) != '0') {
1044 newStringValue = newStringValue.substring(0, j)
1045 + String.valueOf(Integer.parseInt(
1046 newStringValue.substring(j, j + 1)) - 1)
1047 + newStringValue.substring(j + 1);
1048 newValue = 0;
1049 } else {
1050 newStringValue = newStringValue.substring(0, j) + "9"
1051 + newStringValue.substring(j + 1);
1052 }
1053 }
1054 } else {
1055 int indexOfE = oldStringValue.indexOf('E');
1056 char ones = '0';
1057 if (getValue() == 0 && i <= indexOfE) {
1058 ones = '1';
1059 } else if (i > indexOfE) {
1060 if (Double.parseDouble(oldStringValue.substring(indexOfE+1)) == 0.) {
1061 ones = '1';
1062 }
1063 }
1064
1065 if (i > indexOfE) {
1066 if (oldStringValue.charAt(indexOfE + 1) == '+') {
1067 newStringValue = newStringValue.substring(0,
1068 indexOfE + 1) + "-"
1069 + newStringValue.substring(indexOfE + 2, i) + ones
1070 + newStringValue.substring(i + 1);
1071 } else if (oldStringValue.charAt(indexOfE + 1) == '-') {
1072 newStringValue = newStringValue.substring(0,
1073 indexOfE + 1) + "+"
1074 + newStringValue.substring(indexOfE + 2, i) + ones
1075 + newStringValue.substring(i + 1);
1076 } else {
1077 newStringValue = newStringValue.substring(0,
1078 indexOfE + 1) + "-"
1079 + newStringValue.substring(indexOfE + 1, i) + ones
1080 + newStringValue.substring(i + 1);
1081 }
1082 } else {
1083 if (oldStringValue.charAt(0) == '+') {
1084 newStringValue = "-" + newStringValue.substring(1, i)
1085 + ones + newStringValue.substring(i + 1);
1086 } else if (oldStringValue.charAt(0) == '-') {
1087 newStringValue = "+" + newStringValue.substring(1, i)
1088 + ones + newStringValue.substring(i + 1);
1089 } else {
1090 newStringValue = "-" + newStringValue.substring(0, i)
1091 + ones + newStringValue.substring(i + 1);
1092 }
1093 }
1094 }
1095 }
1096 setStringValue(newStringValue);
1097 }
1098
1099
1100
1101
1102
1103 protected void setSelectedDigit(int i)
1104 {
1105 if (editable) {
1106 if (i == selectedDigit) {
1107 return;
1108 }
1109
1110 if ((selectedDigit >= 0) && (selectedDigit < digits.size())) {
1111 (digits.get(selectedDigit)).setSelected(false);
1112 }
1113
1114 if ((i == INCREASE_SELECTION)
1115 || ((i >= 0) && (i < digits.size())
1116 && digits.get(i) instanceof StaticDigit)) {
1117 if (i == INCREASE_SELECTION) {
1118 i = selectedDigit;
1119 }
1120
1121 while ((++i < digits.size())
1122 && digits.get(i) instanceof StaticDigit) {
1123
1124 }
1125
1126 if (i == digits.size()) {
1127 i = -1;
1128
1129 while (digits.get(++i) instanceof StaticDigit) {
1130
1131 }
1132 }
1133 } else if (i == DECREASE_SELECTION) {
1134 i = selectedDigit;
1135
1136 while ((--i >= 0) && digits.get(i) instanceof StaticDigit) {
1137
1138 }
1139
1140 if (i < 0) {
1141 i = digits.size();
1142
1143 while (digits.get(--i) instanceof StaticDigit) {
1144
1145 }
1146 }
1147 }
1148
1149 if ((i >= 0) && (i < digits.size())) {
1150 (digits.get(i)).setSelected(true);
1151 }
1152
1153 selectedDigit = i;
1154 getUpDownButton().setEnabled(selectedDigit >= 0 && selectedDigit < digits.size());
1155 }
1156 }
1157
1158
1159
1160
1161
1162 protected int getSelectedDigit()
1163 {
1164 return selectedDigit;
1165 }
1166
1167
1168
1169
1170
1171 protected void fireSetPerformed(double newValue)
1172 {
1173 Object[] listeners = listenerList.getListenerList();
1174
1175 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1176 if (listeners[i] == SetListener.class) {
1177 ((SetListener)listeners[i + 1]).setPerformed(new SetEvent(
1178 this, newValue));
1179 }
1180 }
1181 }
1182
1183
1184
1185
1186 protected void initDigits()
1187 {
1188 String stringValue = formatter.getString();
1189 char digitValue = 0;
1190 boolean valueOutOfBounds = false;
1191
1192 if (getValue() > getGraphMax() || getValue() < getGraphMin()) {
1193 valueOutOfBounds = true;
1194 }
1195
1196 for (int i = 0; i < stringValue.length(); i++) {
1197 digitValue = stringValue.charAt(i);
1198 (digits.get(i)).setTilting(valueOutOfBounds);
1199
1200 if ((digitValue == '+') || (digitValue == '-')
1201 || (digitValue == 'E') || (digitValue == 'e')
1202 || (digitValue == '.')) {
1203
1204 (digits.get(i)).repaint();
1205
1206
1207 } else {
1208 if (digits.get(i) instanceof ValueDigit) {
1209
1210 ValueDigit digit = ((ValueDigit)digits.get(i));
1211 int newVal = Integer.parseInt(stringValue.substring(i, i
1212 + 1));
1213
1214 if (digit.getValue() != newVal) {
1215 digit.setValue(newVal);
1216 } else {
1217 digit.repaint();
1218 }
1219
1220
1221 } else {
1222 Debug.out(
1223 "Wheelswitch#initDigits(): digits improperly synchronized");
1224 setupValueDigits();
1225 setupLayout();
1226 validate();
1227 repaint();
1228
1229 return;
1230 }
1231 }
1232 }
1233
1234
1235 }
1236
1237
1238
1239
1240 protected void setupLayout()
1241 {
1242 removeAll();
1243
1244 if(!digitsTakeUpAllSpace) {
1245 for (int i = 0; i < hiddenDigits.size(); i++)
1246 add(hiddenDigits.get(i));
1247 }
1248
1249
1250
1251 for (int i = 0; i < digits.size(); i++) {
1252 if ((digits.get(i)).getText().indexOf('E') != -1) {
1253 add(Box.createHorizontalStrut(3));
1254 }
1255
1256 add(digits.get(i));
1257 }
1258
1259 if (unitDigits.size() != 0) {
1260 add(Box.createHorizontalStrut(5));
1261
1262 for (int i = 0; i < unitDigits.size(); i++) {
1263 add(unitDigits.get(i));
1264 }
1265 }
1266
1267 if (editable) {
1268 add(Box.createHorizontalStrut(5));
1269 add(getUpDownButton());
1270 }
1271
1272 if (unitSeparate) {
1273 add(Box.createHorizontalStrut(5));
1274 add(getUnitLabel());
1275 }
1276
1277 preferredSize = null;
1278 minimumSize = null;
1279
1280
1281 }
1282
1283
1284
1285
1286 protected void setupUnitDigits()
1287 {
1288 unitDigits.clear();
1289
1290 String unit = formatter.getUnit();
1291
1292 if (unitSeparate) {
1293 getUnitLabel().setText(unit);
1294
1295 return;
1296 }
1297
1298 if (unit == null) {
1299 return;
1300 }
1301
1302 Digit digit = null;
1303
1304 for (int i = 0; i < unit.length(); i++) {
1305 digit = new StaticDigit(unit.substring(i, i + 1));
1306 digit.setEnhanced(enhanced);
1307 digit.setEnabled(isEnabled());
1308 digit.setAnimated(animated);
1309 unitDigits.add(digit);
1310 }
1311 }
1312
1313
1314
1315
1316 protected void setupValueDigits()
1317 {
1318 digits.clear();
1319 selectedDigit = -1;
1320
1321 String stringValue = formatter.getString();
1322 char digitValue = 0;
1323 Digit digit = null;
1324 if (numberOfAllDigits >= stringValue.length()){
1325 hiddenDigits.clear();
1326 for (int i = 0; i < numberOfAllDigits - stringValue.length(); i++){
1327 digit = new StaticDigit(" ");
1328 digit.setVisible(false);
1329 hiddenDigits.add(digit);
1330 }
1331 }
1332
1333 boolean valueOutOfBounds = false;
1334
1335 if (getValue() > getGraphMax() || getValue() < getGraphMin()) {
1336 valueOutOfBounds = true;
1337 }
1338
1339 for (int i = 0; i < stringValue.length(); i++) {
1340 digitValue = stringValue.charAt(i);
1341
1342 if ((digitValue >= '0') && (digitValue <= '9')) {
1343 digit = new ValueDigit(Integer.parseInt(stringValue.substring(
1344 i, i + 1)));
1345 } else {
1346 digit = new StaticDigit(stringValue.substring(i, i + 1));
1347 }
1348
1349 digit.addMouseListener(mouseHandler);
1350 digit.setEnhanced(enhanced);
1351 digit.setEnabled(isEnabled());
1352 digit.setTilting(valueOutOfBounds);
1353 digit.setAnimated(animated);
1354 digits.add(digit);
1355 }
1356 }
1357
1358
1359
1360
1361
1362 private void setStringValue(String newStringValue)
1363 {
1364 int oldDigitSelection = getSelectedDigit();
1365 int decimalSelection = parseDecimalPosition(oldDigitSelection);
1366
1367 if (debug) {
1368 System.out.println("Wheelswitch::parseDecimalPosition = "
1369 + decimalSelection);
1370 }
1371
1372 double oldValue = formatter.getValue();
1373 String oldStringValue = formatter.getString();
1374
1375 formatter.setString(newStringValue);
1376
1377 double newValue = formatter.getValue();
1378 newStringValue = formatter.getString();
1379
1380 if (oldValue != newValue) {
1381 firePropertyChange(VALUE, oldValue, newValue);
1382 fireSetPerformed(newValue);
1383 }
1384
1385 if (!isEnabled()) {
1386 return;
1387 }
1388
1389 process(oldStringValue, newStringValue);
1390
1391 int newDigitSelection = parseDigitPosition(decimalSelection);
1392
1393 if (debug) {
1394 System.out.println("Wheelswitch::parseDigitPosition = "
1395 + newDigitSelection);
1396 }
1397
1398 if ((newDigitSelection < digits.size()) && (newDigitSelection >= 0)) {
1399 setSelectedDigit(newDigitSelection);
1400 } else {
1401 setSelectedDigit(-1);
1402 }
1403
1404 checkBounds();
1405
1406
1407 }
1408
1409
1410
1411
1412
1413 private int parseDecimalPosition(int digitPosition)
1414 {
1415 if (digitPosition == -1) {
1416 return Integer.MAX_VALUE;
1417 }
1418
1419 String digits = formatter.getString();
1420 int decimalPosition = 0;
1421 int expIndex = digits.indexOf('E');
1422 int dotIndex = digits.indexOf('.');
1423
1424 if ((expIndex == -1) || (digitPosition < expIndex)) {
1425 if (dotIndex != -1) {
1426 decimalPosition += (dotIndex - digitPosition);
1427 } else if (expIndex != -1) {
1428 decimalPosition += (expIndex - digitPosition);
1429 } else {
1430 decimalPosition += (digits.length() - digitPosition);
1431 }
1432
1433 if (decimalPosition > 0) {
1434 decimalPosition--;
1435 }
1436
1437 if (expIndex != -1) {
1438 int exponent = (int)Double.parseDouble(digits.substring(expIndex
1439 + 1));
1440 decimalPosition += exponent;
1441 }
1442 } else {
1443
1444 decimalPosition = 100 * (digits.length() - digitPosition);
1445 }
1446
1447 return decimalPosition;
1448 }
1449
1450
1451
1452
1453
1454 private int parseDigitPosition(int decimalPosition)
1455 {
1456 if (decimalPosition == Integer.MAX_VALUE) {
1457 return -1;
1458 }
1459
1460 String digits = formatter.getString();
1461 int digitPosition = 0;
1462 int expIndex = digits.indexOf('E');
1463 int dotIndex = digits.indexOf('.');
1464
1465 if (((decimalPosition % 100) == 0) && (decimalPosition != 0)) {
1466 decimalPosition /= 100;
1467
1468 if ((expIndex == -1)
1469 || ((digits.length() - expIndex) < decimalPosition)) {
1470 return Integer.MAX_VALUE;
1471 }
1472
1473 digitPosition = digits.length() - decimalPosition;
1474
1475 if ((digits.charAt(digitPosition) == '+')
1476 || (digits.charAt(digitPosition) == '-')) {
1477 return Integer.MAX_VALUE;
1478 }
1479
1480 return digitPosition;
1481 }
1482
1483 if (dotIndex != -1) {
1484 digitPosition += (dotIndex - decimalPosition);
1485 } else if (expIndex != -1) {
1486 digitPosition += (expIndex - decimalPosition - 1);
1487 } else {
1488 digitPosition += (digits.length() - decimalPosition - 1);
1489 }
1490
1491 if (expIndex != -1) {
1492 int exponent = (int)Double.parseDouble(digits.substring(expIndex
1493 + 1));
1494 digitPosition += exponent;
1495 }
1496
1497 if ((expIndex != -1) && (digitPosition >= expIndex)) {
1498 return Integer.MAX_VALUE;
1499 } else if (digitPosition >= digits.length()) {
1500 return Integer.MAX_VALUE;
1501 }
1502
1503 if (digitPosition <= dotIndex) {
1504 digitPosition--;
1505 }
1506
1507 if ((digitPosition < 0)
1508 || ((digitPosition == 0)
1509 && ((digits.charAt(0) == '+') || (digits.charAt(0) == '-')))) {
1510 return Integer.MAX_VALUE;
1511 }
1512
1513 return digitPosition;
1514 }
1515
1516 private synchronized void process(String oldStringValue,
1517 String newStringValue)
1518 {
1519 if ((oldStringValue.length() == newStringValue.length())
1520 && (oldStringValue.indexOf(".") == newStringValue.indexOf("."))
1521 && (oldStringValue.indexOf("E") == newStringValue.indexOf("E"))
1522 && (oldStringValue.indexOf("e") == newStringValue.indexOf("e"))
1523 && (oldStringValue.indexOf("+") == newStringValue.indexOf("+"))
1524 && (oldStringValue.indexOf("-") == newStringValue.indexOf("-"))
1525 && (oldStringValue.indexOf("+", oldStringValue.indexOf("E")) == newStringValue
1526 .indexOf("+", newStringValue.indexOf("E")))
1527 && (oldStringValue.indexOf("+", oldStringValue.indexOf("e")) == newStringValue
1528 .indexOf("+", newStringValue.indexOf("e")))
1529 && (oldStringValue.indexOf("-", oldStringValue.indexOf("e")) == newStringValue
1530 .indexOf("-", newStringValue.indexOf("e")))
1531 && (oldStringValue.indexOf("-", oldStringValue.indexOf("E")) == newStringValue
1532 .indexOf("-", newStringValue.indexOf("E")))) {
1533 initDigits();
1534 } else {
1535 setupValueDigits();
1536 setupLayout();
1537 validate();
1538 repaint();
1539 }
1540 }
1541
1542
1543
1544
1545
1546
1547
1548 public boolean isAnimated()
1549 {
1550 return animated;
1551 }
1552
1553
1554
1555
1556
1557
1558
1559
1560 public void setAnimated(boolean b)
1561 {
1562 if (this.animated == b) {
1563 return;
1564 }
1565
1566 firePropertyChange("animated", this.animated, b);
1567 this.animated = b;
1568
1569 for (int i = 0; i < digits.size(); i++) {
1570 (digits.get(i)).setAnimated(b);
1571 }
1572
1573 for (int i = 0; i < unitDigits.size(); i++) {
1574 (unitDigits.get(i)).setAnimated(b);
1575 }
1576 }
1577
1578
1579
1580
1581
1582
1583 public boolean isUnitSeparate()
1584 {
1585 return unitSeparate;
1586 }
1587
1588
1589
1590
1591
1592
1593
1594 public void setUnitSeparate(boolean unitSeparate)
1595 {
1596 this.unitSeparate = unitSeparate;
1597 }
1598
1599
1600
1601
1602
1603
1604 public AbstractWheelswitchFormatter getFormatter()
1605 {
1606 return formatter;
1607 }
1608
1609
1610
1611
1612
1613
1614
1615 public void setFormatter(AbstractWheelswitchFormatter formatter)
1616 {
1617 if (formatter==null) {
1618 throw new NullPointerException("formatter");
1619 }
1620
1621 String unit = this.formatter.getUnit();
1622 String format = this.formatter.getFormat();
1623 String string = this.formatter.getString();
1624 double value = this.formatter.getValue();
1625 double max = this.formatter.getMaximum();
1626 double min = this.formatter.getMinimum();
1627 int maxDigits = this.formatter.getMaximumDigits();
1628
1629 this.formatter = formatter;
1630
1631 this.formatter.setFormat(format);
1632 this.formatter.setUnit(unit);
1633 this.formatter.setString(string);
1634 this.formatter.setValue(value);
1635 this.formatter.setMaximum(max);
1636 this.formatter.setMinimum(min);
1637 this.formatter.setMaximumDigits(maxDigits);
1638
1639 process(string, formatter.getString());
1640 }
1641
1642
1643
1644
1645
1646
1647 public void setUnitsMaximumFontSize(int max) {
1648 getUnitLabel().setMaximumFontSize(max);
1649 }
1650
1651
1652
1653
1654
1655
1656 public void setUnitsMinimumFontSize(int min) {
1657 getUnitLabel().setMinimumFontSize(min);
1658 }
1659
1660
1661
1662
1663
1664
1665 public int getUnitsMaximumFontSize() {
1666 return getUnitLabel().getMaximumFontSize();
1667 }
1668
1669
1670
1671
1672
1673
1674 public int getUnitsMinimumFontSize() {
1675 return getUnitLabel().getMinimumFontSize();
1676 }
1677
1678
1679
1680
1681
1682 @Override
1683 public void setBackground(Color bg) {
1684 super.setBackground(bg);
1685 getUpDownButton().setBackground(bg);
1686 getUnitLabel().setBackground(bg);
1687 }
1688
1689
1690
1691
1692
1693 @Override
1694 public void setForeground(Color fg) {
1695 super.setForeground(fg);
1696 getUpDownButton().setForeground(fg);
1697 getUnitLabel().setForeground(fg);
1698 }
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709 public void setDigitsTakeUpAllSpace(boolean bool) {
1710 if (digitsTakeUpAllSpace == bool)
1711 return;
1712
1713 firePropertyChange("digitsTakeUpAllSpace", digitsTakeUpAllSpace, bool);
1714 digitsTakeUpAllSpace = bool;
1715
1716 setupValueDigits();
1717 setupUnitDigits();
1718 setupLayout();
1719 validate();
1720 repaint();
1721 }
1722
1723
1724
1725
1726
1727 public boolean getDigitsTakeUpAllSpace() {
1728 return digitsTakeUpAllSpace;
1729 }
1730
1731
1732
1733
1734
1735
1736
1737
1738 public void setNumberOfAllDigits(int numberOfAllDigits) {
1739 if(this.numberOfAllDigits == numberOfAllDigits)
1740 return;
1741
1742 firePropertyChange("numberOfAllDigits", this.numberOfAllDigits, numberOfAllDigits);
1743 this.numberOfAllDigits = numberOfAllDigits;
1744
1745 setupValueDigits();
1746 setupUnitDigits();
1747 setupLayout();
1748 validate();
1749 repaint();
1750 }
1751
1752
1753
1754
1755 public int getNumberOfAllDigits() {
1756 return(numberOfAllDigits);
1757 }
1758
1759 public static void main(String[] args)
1760 {
1761 Wheelswitch ws = new Wheelswitch(WheelswitchFormatter.transformFormat(
1762 "%3.2E2"), 0, "deg:min:sec");
1763
1764 ws.setAnimated(true);
1765 ws.setDigitsTakeUpAllSpace(false);
1766
1767 JFrame f = new JFrame();
1768 f.getContentPane().setLayout(new BorderLayout());
1769 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
1770 f.getContentPane().add(ws, BorderLayout.CENTER);
1771 f.getContentPane().add(new JButton("focus"), BorderLayout.SOUTH);
1772 f.setSize(300, 100);
1773 f.setVisible(true);
1774 }
1775
1776 }
1777
1778