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 java.awt.AlphaComposite;
23 import java.awt.BasicStroke;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Container;
27 import java.awt.Dimension;
28 import java.awt.Font;
29 import java.awt.FontMetrics;
30 import java.awt.GradientPaint;
31 import java.awt.Graphics;
32 import java.awt.Graphics2D;
33 import java.awt.Insets;
34 import java.awt.LayoutManager;
35 import java.awt.event.ActionEvent;
36 import java.awt.event.ActionListener;
37 import java.awt.event.ComponentAdapter;
38 import java.awt.event.ComponentEvent;
39 import java.awt.event.MouseAdapter;
40 import java.awt.event.MouseEvent;
41 import java.awt.event.MouseListener;
42 import java.awt.event.MouseMotionListener;
43 import java.awt.image.BufferedImage;
44 import java.util.Timer;
45 import java.util.TimerTask;
46
47 import javax.swing.AbstractAction;
48 import javax.swing.JButton;
49 import javax.swing.JComponent;
50 import javax.swing.JFrame;
51 import javax.swing.JPanel;
52 import javax.swing.TransferHandler;
53
54 import com.cosylab.application.state.State;
55 import com.cosylab.application.state.StateFactory;
56 import com.cosylab.application.state.StateOriginator;
57 import com.cosylab.events.SetAdapter;
58 import com.cosylab.events.SetEvent;
59 import com.cosylab.events.SetListener;
60 import com.cosylab.gui.components.customizer.AbstractCustomizerPanel;
61 import com.cosylab.gui.components.ledder.LedPaint;
62 import com.cosylab.gui.components.ledder.LedPaintParameters;
63 import com.cosylab.gui.components.range2.LinearRange;
64 import com.cosylab.gui.components.range2.RangedValueController;
65 import com.cosylab.gui.components.range2.RangedValueEvent;
66 import com.cosylab.gui.components.range2.RangedValueListener;
67 import com.cosylab.gui.components.range2.RangedValuePolicy;
68 import com.cosylab.gui.components.range2.RescalingValuePolicy;
69 import com.cosylab.gui.components.range2.Tick;
70 import com.cosylab.gui.components.range2.TickParameters;
71 import com.cosylab.gui.components.range2.TrimValuePolicy;
72 import com.cosylab.gui.components.util.ColorHelper;
73 import com.cosylab.gui.components.util.CosyTransferHandler;
74 import com.cosylab.gui.components.util.FontHelper;
75 import com.cosylab.gui.components.util.PaintHelper;
76 import com.cosylab.gui.components.util.PopupManageable;
77 import com.cosylab.gui.components.util.PopupManager;
78 import com.cosylab.gui.components.util.ScreenCapturer;
79 import com.cosylab.util.PrintfFormat;
80
81
82
83
84
85
86
87
88
89
90
91 public class DialKnob extends JComponent implements PopupManageable,
92 StateOriginator, CosyTransferHandler.MouseFilter
93 {
94 private static final long serialVersionUID = 1L;
95
96
97
98
99
100
101
102
103
104
105 protected class ValueListener implements RangedValueListener {
106
107
108
109
110 public void valueChanged(RangedValueEvent event) {
111 if (!isEnabled()) {
112 return;
113 }
114 if (event.isMinOrMaxChanged()) {
115 renderer.clearScale();
116 }
117
118 if (autoSynchronize) {
119 getAutoSyncTimer().restart();
120 lastValueTimestamp = System.currentTimeMillis();
121 }
122
123 renderer.checkValue();
124 repaint();
125 }
126
127 }
128
129
130
131
132
133 protected class MouseHandler extends MouseAdapter implements MouseListener, MouseMotionListener
134 {
135 private boolean inhibit;
136 private boolean isDragged = false;
137 private double angleBackground;
138 private double currentMouseAngle;
139 private double initMouseAngle;
140 private double initUserRelativeValue;
141
142
143
144
145
146
147
148
149 public void inhibit(boolean newInhibit)
150 {
151 inhibit = newInhibit;
152 }
153
154
155
156
157
158
159 public void mouseDragged(MouseEvent arg0)
160 {
161 if (inhibit || !isDragged) {
162 return;
163 }
164
165
166
167
168
169
170
171
172
173
174 double mouseAngle = getMouseAngle(arg0);
175 double ratio = (rangedValue.getMaximum()-rangedValue.getMinimum())/(userRangedValue.getMaximum()-userRangedValue.getMinimum());
176 double valueToSet = initUserRelativeValue
177 + (angleBackground + mouseAngle - initMouseAngle) / 1.5 / Math.PI * ratio;
178 valueToSet = (valueToSet > 1.0 ? 1.0
179 : (valueToSet < 0.0 ? 0.0 : valueToSet));
180
181 if (valueToSet == 0.0 || valueToSet == 1.0) {
182 mousePressed(arg0);
183 }
184 userRangedValue.setRelativeValue(valueToSet);
185 }
186
187
188
189
190
191
192 public void mousePressed(MouseEvent arg0)
193 {
194 if (isMouseOutside(arg0) || inhibit) {
195 return;
196 }
197
198 isDragged = true;
199 allowAutoSync = false;
200
201 int relativeX = arg0.getX() - renderer.knobCenterX;
202 int relativeY = arg0.getY() - renderer.knobCenterY;
203 double tangens = (double)relativeY / relativeX;
204 currentMouseAngle = (relativeX >= 0.0
205 ? Math.atan(tangens) + Math.PI / 2
206 : Math.atan(tangens) + 1.5 * Math.PI);
207 initMouseAngle = currentMouseAngle;
208 angleBackground = 0.0;
209 initUserRelativeValue = userRangedValue.getRelativeValue();
210 }
211
212
213
214
215
216
217 public void mouseReleased(MouseEvent arg0)
218 {
219 isDragged = false;
220 if (arg0.getButton() == MouseEvent.BUTTON1 && autoSynchronize){
221 allowAutoSync = true;
222 lastValueTimestamp = System.currentTimeMillis();
223 }
224 }
225
226
227 private double getMouseAngle(MouseEvent arg0)
228 {
229 int relativeX = arg0.getX() - renderer.knobCenterX;
230 int relativeY = arg0.getY() - renderer.knobCenterY;
231 double tangens = (double)relativeY / relativeX;
232 double newAngle = (relativeX >= 0.0
233 ? Math.atan(tangens) + Math.PI / 2
234 : Math.atan(tangens) + 1.5 * Math.PI);
235
236 if (Math.abs(newAngle - currentMouseAngle) > Math.PI) {
237 if (newAngle > currentMouseAngle) {
238 angleBackground -= 2 * Math.PI;
239 } else {
240 angleBackground += 2 * Math.PI;
241 }
242 }
243
244 currentMouseAngle = newAngle;
245
246 return currentMouseAngle;
247 }
248
249
250 private boolean isMouseOutside(MouseEvent arg0)
251 {
252 int x = arg0.getX();
253 int y = arg0.getY();
254 int relativeX = x - renderer.knobCenterX;
255 int relativeY = y - renderer.knobCenterY;
256
257 if (relativeX * relativeX + relativeY * relativeY > renderer.knobDiameter * renderer.knobDiameter / 4.0) {
258 allowAutoSync = true;
259 lastValueTimestamp = System.currentTimeMillis();
260 return true;
261 }
262
263 return false;
264 }
265
266 public void mouseMoved(MouseEvent e) {
267
268
269 }
270 }
271
272
273
274
275
276
277 protected class Renderer implements TickParameters
278 {
279
280 private int knobCenterX;
281 private int knobCenterY;
282 private int knobDiameter;
283 private BufferedImage knobImage;
284 private BufferedImage markerImage;
285 private BufferedImage scaleImage;
286 private FontMetrics fontMetrics;
287 private Tick[] ticks;
288 private boolean checkedValue;
289 private boolean prohibitDrawing;
290 private int titleHeight;
291 private int fontHeight;
292 private int height;
293 private int markerImageSize;
294 private int scaleSize;
295 private int size;
296 private int width;
297
298 public void checkValue()
299 {
300 if (checkedValue != (userRangedValue.getValue() == labelValue)) {
301 checkedValue = (userRangedValue.getValue() == labelValue);
302 markerImage = null;
303 }
304 }
305
306
307
308
309
310 public void clearBuffer()
311 {
312 knobImage = null;
313 scaleImage = null;
314 markerImage = null;
315 }
316
317
318
319
320
321
322 public void clearScale()
323 {
324 scaleImage = null;
325 }
326
327
328
329
330
331
332
333
334 public void initialize(Graphics2D g2d)
335 {
336 width = DialKnob.this.getWidth();
337 height = DialKnob.this.getHeight();
338 fontHeight = (resizable ? 5 + Math.min(width, height) / 25
339 : FontHelper.getDefaultFontSize());
340 g2d.setFont(FontHelper.getFontWithSize(fontHeight, g2d.getFont()));
341 fontMetrics = g2d.getFontMetrics();
342 titleHeight = (titleVisible && title!=null && title.length()>0 ? fontHeight * 12 / 10 : 0);
343 size = Math.min(width, height - titleHeight);
344
345 if (size <= 0) {
346 titleHeight = 0;
347 size = Math.min(width, height);
348 }
349
350 scaleSize = (size - 2 * fontHeight * 10 / 8);
351 knobDiameter = scaleSize * 8 / 10;
352
353 if (knobDiameter <= 0) {
354 prohibitDrawing = true;
355 if (isEditable())mouseHandler.inhibit(true);
356
357 return;
358 }
359
360 if (enhanced) {
361 g2d.addRenderingHints(PaintHelper.getAntialiasingHints());
362 }
363
364 knobCenterX = width / 2;
365 knobCenterY = height / 2 + titleHeight;
366 markerImageSize = Math.max(knobDiameter / 8, 10);
367 prohibitDrawing = false;
368 if (isEditable())getMouseHandler().inhibit(false);
369 }
370
371
372
373
374
375 public int measureTick(double position, String text)
376 {
377 return fontMetrics.stringWidth(text);
378 }
379
380
381
382
383
384
385 public void paintKnob(Graphics2D g2d)
386 {
387 if (prohibitDrawing) {
388 return;
389 }
390
391 if (knobImage == null) {
392 knobImage = new BufferedImage(knobDiameter, knobDiameter,
393 BufferedImage.TYPE_4BYTE_ABGR);
394
395 Graphics2D tmpG2d = knobImage.createGraphics();
396
397 if (enhanced) {
398 tmpG2d.addRenderingHints(PaintHelper.getAntialiasingHints());
399 tmpG2d.setPaint(new GradientPaint(0, 0, Color.WHITE,
400 knobDiameter, knobDiameter,
401 new Color(0.01f, 0, 0.3f)));
402 tmpG2d.fillOval(0, 0, knobDiameter, knobDiameter);
403 }
404
405 int edge = knobDiameter / 25;
406 tmpG2d.setColor(new Color(107, 109, 169));
407 tmpG2d.fillOval(edge, edge, knobDiameter - 2 * edge,
408 knobDiameter - 2 * edge);
409 }
410
411 g2d.drawImage(knobImage, null, (width - knobDiameter) / 2,
412 knobCenterY - knobDiameter / 2);
413 }
414
415
416
417
418
419
420
421 public void paintMarker(Graphics2D g2d)
422 {
423 if (prohibitDrawing) {
424 return;
425 }
426
427 if (markerImageSize == 0) {
428 return;
429 }
430
431 int x = knobCenterX;
432 int y = knobCenterY;
433 int r = knobDiameter / 2 - markerImageSize;
434 float strokeWidth = Math.max(knobDiameter / 60.f, 3.f);
435 int r1 = knobDiameter / 2 + (int)strokeWidth / 2;
436 int r2 = knobDiameter / 2 * 17 / 15 - (int)strokeWidth / 2;
437
438
439
440 double val = (rangedValue.getValue() - rangedValue.getMinimum()) / (rangedValue
441 .getMaximum() - rangedValue.getMinimum());
442 double angle = (val - 0.5) * Math.PI * 1.5;
443 boolean valueCheck = true;
444 if (labelValue>getGraphMax() || labelValue<getGraphMin()) valueCheck = false;
445
446
447
448 if(!rangeColors) {
449 markerColor = (valueCheck ? Color.GREEN : Color.YELLOW);
450 } else if(!valueCheck) {
451 if (labelValue < getGraphMin()) angle = angle-overLimitAngle;
452 else angle = angle+overLimitAngle;
453 markerColor = outOfBoundsColor;
454 } else if( (val <= lowAlarmLimit) || (val >= 1.0-highAlarmLimit) ){
455 markerColor = alarmColor;
456 } else if( (val <= lowWarningLimit) || (val >= 1.0-highWarningLimit) ){
457 markerColor = warningColor;
458 } else{
459 markerColor = normalColor;
460 }
461 g2d.setColor(markerColor);
462
463 g2d.setStroke(new BasicStroke(strokeWidth));
464 g2d.drawLine((int)(x + r1 * Math.sin(angle)),
465 (int)(y - r1 * Math.cos(angle)),
466 (int)(x + r2 * Math.sin(angle)), (int)(y - r2 * Math.cos(angle)));
467
468 if (markerImage == null) {
469 markerImage = getMarkerImage();
470 }
471
472
473 val = userRangedValue.getValue();
474 if (val>rangedValue.getMaximum()) val = rangedValue.getMaximum();
475 if (val<rangedValue.getMinimum()) val = rangedValue.getMinimum();
476 val = (val - rangedValue.getMinimum()) / (rangedValue
477 .getMaximum() - rangedValue.getMinimum());
478 angle = (val - 0.5) * Math.PI * 1.5;
479
480
481
482
483 g2d.drawImage(markerImage, null,
484 (int)(x + r * Math.sin(angle) - markerImageSize / 2),
485 (int)(y - r * Math.cos(angle) - markerImageSize / 2));
486
487 if (enhanced) {
488 g2d.setComposite(AlphaComposite.getInstance(
489 AlphaComposite.SRC_ATOP, 0.5f));
490 }
491
492 if (editable) {
493 g2d.setColor(userRangedValue.getValue() == labelValue ? markerColor
494 : Color.RED);
495 } else {
496 g2d.setColor(Color.GRAY);
497 }
498
499 g2d.drawLine((int)(x + r1 * Math.sin(angle)),
500 (int)(y - r1 * Math.cos(angle)),
501 (int)(x + r2 * Math.sin(angle)), (int)(y - r2 * Math.cos(angle)));
502
503
504 if (enhanced) {
505 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
506 }
507
508 g2d.setStroke(new BasicStroke());
509 }
510
511
512
513
514
515
516 public void paintTicks(Graphics2D g2d)
517 {
518 if (prohibitDrawing) {
519 return;
520 }
521
522 if (scaleImage == null) {
523 scaleImage = getScaleImage();
524 }
525
526 g2d.drawImage(scaleImage, null, knobCenterX - size / 2,
527 knobCenterY - size / 2);
528 }
529
530
531
532
533
534
535 public void paintTitleLabel(Graphics2D g2d)
536 {
537 if (titleHeight <= 0 || title == null || title.length()==0) {
538 return;
539 }
540
541
542 g2d.setColor((isEnabled() ? getForeground() : Color.GRAY));
543 g2d.drawString(title, (width - fontMetrics.stringWidth(title)) / 2,
544 titleHeight);
545 }
546
547
548
549
550
551
552 public void paintValueLabel(Graphics2D g2d)
553 {
554 String text;
555
556 try {
557
558 text = this.formatNumber(labelValue);
559 } catch (Exception e) {
560 text = Double.toString(labelValue);
561 }
562
563 text += ((units == null || !unitsVisible) ? "" : " " + units);
564
565 if (fontMetrics.stringWidth(text) >= knobDiameter) {
566 return;
567 }
568
569
570 g2d.setColor((isEnabled() ? getForeground() : Color.LIGHT_GRAY));
571 g2d.drawString(text, (width - fontMetrics.stringWidth(text)) / 2,
572 knobCenterY);
573 }
574
575 private BufferedImage getMarkerImage()
576 {
577 BufferedImage markerImage = new BufferedImage(markerImageSize,
578 markerImageSize, BufferedImage.TYPE_4BYTE_ABGR);
579 Graphics2D tmpG2d = markerImage.createGraphics();
580
581 if (enhanced) {
582 tmpG2d.addRenderingHints(PaintHelper.getAntialiasingHints());
583 }
584
585 Color c = null;
586 if (editable) {
587 c = (userRangedValue.getValue() == labelValue? Color.GREEN : Color.RED);
588 } else {
589 c = Color.GRAY;
590 }
591
592
593 if (enhanced) {
594 LedPaintParameters param = new LedPaintParameters();
595 param.lightX = -0.2;
596 param.lightY = -0.2;
597 param.shadowIntensity = 4;
598 param.radius = markerImageSize * 10 / 8;
599 param.borderSize = 0;
600 param.color = c;
601 tmpG2d.setPaint(new LedPaint(param,markerImageSize / 2,markerImageSize / 2));
602 } else {
603 tmpG2d.setColor(c);
604 }
605
606 tmpG2d.fillOval(0, 0, markerImageSize, markerImageSize);
607
608 return markerImage;
609 }
610
611 private BufferedImage getScaleImage()
612 {
613 BufferedImage image = new BufferedImage(size, size,
614 BufferedImage.TYPE_4BYTE_ABGR);
615 Graphics2D g2d = image.createGraphics();
616
617 if (enhanced) {
618 g2d.addRenderingHints(PaintHelper.getAntialiasingHints());
619 }
620
621 int width = (scaleSize - knobDiameter) / 4;
622 int size0 = scaleSize - 4 * width;
623 g2d.setColor((tilting ? ColorHelper.getAlarm()
624 : getBackground()));
625 g2d.setStroke(new BasicStroke(width));
626
627 int size1 = scaleSize - 3 * width;
628 g2d.drawOval((size - size1) / 2, (size - size1) / 2, size1, size1);
629
630 g2d.setStroke(new BasicStroke());
631 g2d.setColor(ColorHelper.getCosyControlShadow());
632
633 int size2 = scaleSize - 2 * width;
634 g2d.drawOval((size - size2) / 2, (size - size2) / 2, size2, size2);
635
636
637 g2d.setColor((isEnabled() ? getForeground() : Color.GRAY));
638 g2d.setFont(FontHelper.getFontWithSize(fontHeight, g2d.getFont()));
639
640
641 ticks = rangedValue.calculateTicks((int)(0.75 * Math.PI * (scaleSize - fontHeight)),this);
642
643 if (ticks == null) {
644 return image;
645 }
646
647 g2d.rotate(-Math.PI * 3 / 4, size / 2, size / 2);
648
649 double prop = 0.0;
650 if (getMinimum() > getMaximum()) return image;
651 for (int i = 0; i < ticks.length; i++) {
652 g2d.rotate((ticks[i].proportional - prop) * Math.PI * 3 / 2,
653 size / 2, size / 2);
654 prop = ticks[i].proportional;
655
656 if (ticks[i].major) {
657 g2d.drawLine(size / 2, (size - size0) / 2, size / 2,
658 (size - size2) / 2 + 1);
659
660 String text = ticks[i].text;
661
662 if (text != null) {
663 g2d.drawString(text,
664 (size - fontMetrics.stringWidth(text)) / 2,
665 (size - size2) / 2 - 5);
666 }
667 } else {
668 g2d.drawLine(size / 2, (size - size0) / 2, size / 2,
669 (size - size2) / 4 + (size - size0) / 4 + 1);
670 }
671 }
672
673 return image;
674 }
675
676
677
678
679
680 public String formatNumber(double x) {
681 return formatter.sprintf(x);
682 }
683 }
684
685 private class ResizeListener extends ComponentAdapter
686 {
687
688
689
690
691 public void componentResized(ComponentEvent cEvent)
692 {
693 renderer.clearBuffer();
694 repaint();
695 }
696 }
697
698
699
700
701
702
703
704
705 protected class TiltHandler extends Timer
706 {
707 private class TiltTask extends TimerTask
708 {
709
710
711
712 public void run()
713 {
714 if (numberOfTilts >= MAX_NUMBER_OF_TILTS) {
715 cancel();
716 tilting = false;
717 } else {
718 numberOfTilts++;
719 tilting = !tilting;
720 }
721
722 renderer.clearScale();
723 repaint();
724 }
725 }
726
727 private final int MAX_NUMBER_OF_TILTS = 3;
728 private final long TILT_RATE = 200;
729 private int numberOfTilts = MAX_NUMBER_OF_TILTS;
730
731
732
733
734
735 public void tilt()
736 {
737 if (numberOfTilts >= MAX_NUMBER_OF_TILTS) {
738 numberOfTilts = 0;
739 schedule(new TiltTask(), 0, TILT_RATE);
740 } else {
741 numberOfTilts = 0;
742 }
743 }
744 }
745
746
747
748
749
750
751 protected class UserValueListener implements RangedValueListener
752 {
753
754
755
756
757 public void valueChanged(RangedValueEvent rvEvent)
758 {
759 if (rvEvent.isValueChanged()) {
760
761
762
763
764
765 notifyListeners(userRangedValue.getRawValue());
766 }
767 if (autoSynchronize) {
768 getAutoSyncTimer().stop();
769 lastValueTimestamp = System.currentTimeMillis();
770 }
771
772
773
774 renderer.checkValue();
775
776 if (!isEnabled()) {
777 return;
778 }
779
780 DialKnob.this.repaint();
781 }
782 }
783
784 private JButton syncButton;
785 private RangedValuePolicy policy;
786 protected MouseHandler mouseHandler;
787 protected PrintfFormat formatter;
788 protected RangedValueController userRangedValue;
789 protected Renderer renderer;
790 protected String format;
791 protected String title;
792 protected String units;
793 protected boolean titleVisible;
794 protected RangedValueController rangedValue;
795 private AbstractCustomizerPanel customizer;
796 private PopupManager popupManager;
797 private TiltHandler tiltHandler;
798 private boolean editable;
799 private boolean enhanced = true;
800 private boolean painting;
801 private boolean popupEnabled;
802 private boolean resizable = true;
803 private boolean tilting;
804 private boolean tiltingEnabled;
805 private double labelValue;
806 private boolean unitsVisible = true;
807
808
809
810
811
812 private boolean rangeColors = true;
813
814
815 private double lowAlarmLimit = 0.05;
816 private double lowWarningLimit= 0.2;
817 private double highWarningLimit= 0.2;
818 private double highAlarmLimit= 0.05;
819
820
821 private Color normalColor = new Color(0, 192, 0);
822 private Color alarmColor = new Color(239,0,0);
823 private Color warningColor = new Color(0xEEEC300);
824 private Color outOfBoundsColor = new Color(239,0,0);
825
826
827
828
829 private double overLimitAngle = 5.0 / 180 * Math.PI;
830
831 private Color markerColor = null;
832
833
834
835
836 private boolean autoSynchronize = false;
837
838
839
840 private long autoSynchronizeDelay = 2000;
841
842 private boolean allowAutoSync = true;
843 long lastValueTimestamp = System.currentTimeMillis();
844
845
846
847
848 public DialKnob()
849 {
850 this(null, 0, 0);
851 }
852
853
854
855
856
857
858 public DialKnob(String newLabel)
859 {
860 this(newLabel, -20, -20);
861 }
862
863
864
865
866
867
868
869
870 public DialKnob(String newLabel, double newUserValue, double newValue)
871 {
872 super();
873
874 title = newLabel;
875
876 format = "%3.2f";
877 formatter = new PrintfFormat(format);
878
879 renderer = new Renderer();
880
881 userRangedValue = new RangedValueController();
882 userRangedValue.setRange(new LinearRange());
883
884 labelValue = newValue;
885
886 if (newUserValue == 0) {
887 userRangedValue.setValue(0, 1, 0);
888 } else {
889 userRangedValue.setValue(newUserValue - Math.abs(newUserValue),
890 newUserValue + 3 * Math.abs(newUserValue), newUserValue);
891 }
892
893 userRangedValue.addPolicy(new TrimValuePolicy());
894 userRangedValue.addRangedValueListener(new UserValueListener());
895
896 addComponentListener(new ResizeListener());
897
898 rangedValue = new RangedValueController();
899 rangedValue.setRange(new LinearRange());
900
901 if (newValue == 0) {
902 rangedValue.setValue(0, 1, 0);
903 } else {
904 rangedValue.setValue(newValue - Math.abs(newValue),
905 newValue + 3 * Math.abs(newValue), newValue);
906 }
907
908 policy = new RescalingValuePolicy();
909 rangedValue.addPolicy(policy);
910 rangedValue.addRangedValueListener(new ValueListener());
911
912
913 setLayout(new LayoutManager() {
914 public void removeLayoutComponent(Component comp) {
915 }
916
917 public void layoutContainer(Container parent) {
918 Dimension size = getSyncButton().getPreferredSize();
919 int x = getWidth()-size.width-getInsets().right-2;
920 int y = getInsets().top+2;
921 getSyncButton().setBounds(x,y,size.width,size.height);
922 }
923
924 public void addLayoutComponent(String name, Component comp) {
925 }
926
927 public Dimension minimumLayoutSize(Container parent) {
928 return null;
929 }
930
931 public Dimension preferredLayoutSize(Container parent) {
932 return null;
933 }
934 });
935
936
937 add(getSyncButton());
938
939 setBackground(ColorHelper.getCosyControl());
940 setPreferredSize(new Dimension(200, 200));
941 setMinimumSize(new Dimension(85, 85));
942 setOpaque(true);
943 setVisible(true);
944 setPopupEnabled(true);
945 }
946
947 private JButton getSyncButton() {
948 if (syncButton == null) {
949 syncButton = new JButton("Sync");
950 syncButton.setOpaque(false);
951 syncButton.setMargin(new Insets(0, 1, 0, 1));
952 syncButton.setFont(new Font(syncButton.getFont().getName(), Font.PLAIN, 9));
953 syncButton.addActionListener(new ActionListener() {
954 public void actionPerformed(ActionEvent e) {
955 synchronize();
956 }
957 });
958
959 }
960
961 return syncButton;
962 }
963
964
965
966
967
968
969
970 public AbstractCustomizerPanel getCustomizer()
971 {
972 if (customizer == null) {
973 customizer = AbstractCustomizerPanel.findCustomizer(this);
974 }
975
976 return customizer;
977 }
978
979
980
981
982
983
984
985
986
987 public void setEnhanced(boolean b)
988 {
989 if (enhanced == b) {
990 return;
991 }
992
993 enhanced = b;
994 renderer.clearBuffer();
995 repaint();
996 firePropertyChange("enhanced", !b, b);
997 }
998
999
1000
1001
1002
1003
1004 public boolean isEnhanced()
1005 {
1006 return enhanced;
1007 }
1008
1009
1010
1011
1012
1013
1014 public void setFormat(String newFormat)
1015 {
1016 String oldFormat = format;
1017 format = newFormat;
1018 formatter = new PrintfFormat(format);
1019 firePropertyChange("format", oldFormat, newFormat);
1020 renderer.clearBuffer();
1021 if (!isEnabled()) {
1022 return;
1023 }
1024
1025 repaint();
1026 }
1027
1028
1029
1030
1031
1032
1033 public String getFormat()
1034 {
1035 return format;
1036 }
1037
1038
1039
1040
1041
1042
1043 public void setUserMax(double newMax)
1044 {
1045
1046 double oldMax = userRangedValue.getMaximum();
1047 userRangedValue.setMaximum(newMax);
1048
1049 firePropertyChange("userMax", oldMax, newMax);
1050 if (newMax<rangedValue.getMaximum()) setGraphMax(newMax);
1051 }
1052
1053
1054
1055
1056
1057
1058 public void setGraphMax(double newMax)
1059 {
1060 double oldMax = rangedValue.getMaximum();
1061 rangedValue.setValue(rangedValue.getMinimum(), newMax,rangedValue.getValue());
1062 firePropertyChange("graphMax", oldMax, newMax);
1063 }
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 public void setMaximum(double value) {
1074 double old = getMaximum();
1075 setUserMax(value);
1076 setGraphMax(value);
1077 firePropertyChange("maximum",old,value);
1078 }
1079
1080
1081
1082
1083
1084
1085 public double getUserMax()
1086 {
1087 return userRangedValue.getMaximum();
1088 }
1089
1090
1091
1092
1093
1094
1095 public double getMaximum()
1096 {
1097 return getUserMax();
1098 }
1099
1100
1101
1102
1103
1104 public double getGraphMax()
1105 {
1106 return rangedValue.getMaximum();
1107 }
1108
1109
1110
1111
1112
1113
1114
1115 public void setUserMin(double newMin)
1116 {
1117 double oldMin = userRangedValue.getMinimum();
1118 userRangedValue.setMinimum(newMin);
1119
1120 firePropertyChange("userMin", oldMin, newMin);
1121 if (newMin<rangedValue.getMinimum()) setGraphMin(newMin);
1122 }
1123
1124
1125
1126
1127
1128
1129 public void setGraphMin(double newMin)
1130 {
1131 double oldMin = rangedValue.getMinimum();
1132 rangedValue.setValue(newMin, rangedValue.getMaximum(),rangedValue.getValue());
1133 firePropertyChange("graphMin", oldMin, newMin);
1134 }
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 public void setMinimum(double value) {
1145 double oldValue = getMinimum();
1146 setGraphMin(value);
1147 setUserMin(value);
1148 firePropertyChange("minimum", oldValue, value);
1149 }
1150
1151
1152
1153
1154
1155
1156 public double getMinimum()
1157 {
1158 return getUserMin();
1159 }
1160
1161
1162
1163
1164
1165 public double getUserMin() {
1166 return userRangedValue.getMinimum();
1167 }
1168
1169
1170
1171
1172
1173
1174 public double getGraphMin() {
1175 return rangedValue.getMinimum();
1176 }
1177
1178
1179
1180
1181
1182
1183
1184 public boolean isPopupEnabled()
1185 {
1186 return popupEnabled;
1187 }
1188
1189
1190
1191
1192
1193
1194
1195 public PopupManager getPopupManager()
1196 {
1197 if (popupManager == null) {
1198 popupManager = new PopupManager(this, false);
1199 popupManager.addAction(new AbstractAction("Synchronize") {
1200 private static final long serialVersionUID = 1L;
1201
1202 public void actionPerformed(ActionEvent e)
1203 {
1204 synchronize();
1205 }
1206 });
1207 popupManager.addAction(new AbstractAction("Preferences...") {
1208 private static final long serialVersionUID = 1L;
1209
1210 public void actionPerformed(ActionEvent e)
1211 {
1212 getCustomizer().showDialog();
1213 }
1214 });
1215 popupManager.addAction(new AbstractAction("Capture Screen...") {
1216 private static final long serialVersionUID = 1L;
1217
1218 public void actionPerformed(ActionEvent e)
1219 { ScreenCapturer sc = new ScreenCapturer(DialKnob.this);
1220 sc.showScreenDialog();
1221 }
1222
1223 });
1224 }
1225
1226 return popupManager;
1227 }
1228
1229
1230
1231
1232
1233
1234
1235 public void setResizable(boolean b)
1236 {
1237 if (b == resizable) {
1238 return;
1239 }
1240
1241 resizable = b;
1242
1243 renderer.clearBuffer();
1244 repaint();
1245 firePropertyChange("resizable", !b, b);
1246 }
1247
1248
1249
1250
1251
1252
1253 public boolean isResizable()
1254 {
1255 return resizable;
1256 }
1257
1258
1259
1260
1261
1262
1263
1264
1265 public void setState(State state)
1266 {
1267 setFormat(state.getString("format", getFormat()));
1268 setMaximum(state.getDouble("maximum", getMaximum()));
1269 setMinimum(state.getDouble("minimum", getMinimum()));
1270 setTitle(state.getString("title", getTitle()));
1271 setUnits(state.getString("units", getUnits()));
1272 setTitleVisible(state.getBoolean("titleVisible", isTitleVisible()));
1273 setEnhanced(state.getBoolean("enhanced", isEnhanced()));
1274 setResizable(state.getBoolean("resizable", isResizable()));
1275 setTiltingEnabled(state.getBoolean("tiltingEnabled", isTiltingEnabled()));
1276 }
1277
1278
1279
1280
1281
1282
1283
1284
1285 public State getState()
1286 {
1287 State state = StateFactory.createState();
1288
1289 state.putString("format", getFormat());
1290 state.putDouble("maximum", getMaximum());
1291 state.putDouble("minimum", getMinimum());
1292 state.putString("title", getTitle());
1293 state.putString("units", getUnits());
1294 state.putBoolean("titleVisible", isTitleVisible());
1295 state.putBoolean("enhanced", isEnhanced());
1296 state.putBoolean("resizable", isResizable());
1297 state.putBoolean("tiltingEnabled", isTiltingEnabled());
1298
1299 return state;
1300 }
1301
1302
1303
1304
1305
1306
1307 public void setTitle(String string)
1308 {
1309 String oldTitle = title;
1310 title = string;
1311 firePropertyChange("title", oldTitle, string);
1312
1313 if (!isEnabled()) {
1314 return;
1315 }
1316
1317 repaint();
1318 }
1319
1320
1321
1322
1323
1324
1325 public String getTitle()
1326 {
1327 return title;
1328 }
1329
1330
1331
1332
1333
1334
1335 public void setTitleVisible(boolean b)
1336 {
1337 if (titleVisible == b) return;
1338 boolean oldB = titleVisible;
1339 titleVisible = b;
1340 firePropertyChange("titleVisible", oldB, b);
1341
1342 if (!isEnabled()) {
1343 return;
1344 }
1345
1346 repaint();
1347 }
1348
1349
1350
1351
1352
1353
1354 public boolean isTitleVisible()
1355 {
1356 return titleVisible;
1357 }
1358
1359
1360
1361
1362
1363
1364 public void setUnits(String newUnit)
1365 {
1366 String oldUnits = units;
1367 units = newUnit;
1368 firePropertyChange("units", oldUnits, newUnit);
1369
1370 if (!isEnabled()) {
1371 return;
1372 }
1373
1374 repaint();
1375 }
1376
1377
1378
1379
1380
1381
1382 public String getUnits()
1383 {
1384 return units;
1385 }
1386
1387
1388
1389
1390
1391
1392 public void setUserValue(double newUserValue)
1393 {
1394 double oldUserValue = userRangedValue.getValue();
1395
1396 userRangedValue.setValue(newUserValue);
1397 renderer.checkValue();
1398 firePropertyChange("userValue", oldUserValue, getUserValue());
1399
1400 if (autoSynchronize) {
1401 getAutoSyncTimer().stop();
1402 lastValueTimestamp = System.currentTimeMillis();
1403 }
1404
1405 if (!isEnabled()) {
1406 return;
1407 }
1408
1409 repaint();
1410 }
1411
1412
1413
1414
1415
1416
1417 public double getUserValue()
1418 {
1419 return userRangedValue.getValue();
1420 }
1421
1422
1423
1424
1425
1426
1427 public void setValue(double newValue)
1428 {
1429
1430 double oldValue = getValue();
1431
1432 if (oldValue == newValue) {
1433 return;
1434 }
1435
1436 labelValue = newValue;
1437 renderer.checkValue();
1438
1439 rangedValue.setValue(newValue);
1440
1441
1442 if (autoSynchronize) {
1443 if (oldValue != newValue) {
1444 getAutoSyncTimer().restart();
1445 } else {
1446 if (!getAutoSyncTimer().isRunning()) {
1447 getAutoSyncTimer().start();
1448 }
1449 }
1450
1451 }
1452
1453 firePropertyChange("value", oldValue, getValue());
1454
1455 if ((newValue > userRangedValue.getMaximum()
1456 || newValue < userRangedValue.getMinimum()) && tiltingEnabled) {
1457 getTiltHandler().tilt();
1458 }
1459
1460 }
1461
1462
1463
1464
1465
1466
1467 public double getValue()
1468 {
1469 return labelValue;
1470 }
1471
1472
1473
1474
1475
1476
1477
1478 public void addSetListener(SetListener listener)
1479 {
1480 listenerList.add(SetListener.class, listener);
1481 }
1482
1483
1484
1485
1486
1487
1488
1489 public void setEditable(boolean b)
1490 {
1491 if (editable == b) {
1492 return;
1493 }
1494
1495 editable = b;
1496
1497 if (b) {
1498 addMouseListener(getMouseHandler());
1499 addMouseMotionListener(getMouseHandler());
1500 } else {
1501 removeMouseListener(getMouseHandler());
1502 removeMouseMotionListener(getMouseHandler());
1503 }
1504
1505 firePropertyChange("editable", !b, b);
1506
1507 if (!isEnabled()) {
1508 return;
1509 }
1510
1511 renderer.markerImage=null;
1512 repaint();
1513 }
1514
1515
1516
1517
1518
1519
1520 public boolean isEditable()
1521 {
1522 return editable;
1523 }
1524
1525
1526
1527
1528
1529
1530 public void setEnabled(boolean enabled)
1531 {
1532 super.setEnabled(enabled);
1533
1534 renderer.clearBuffer();
1535 repaint();
1536 }
1537
1538
1539
1540
1541
1542
1543 public void setPopupEnabled(boolean b)
1544 {
1545 if (popupEnabled != b) {
1546 if (b) {
1547 addMouseListener(getPopupManager().getMouseHook());
1548 } else {
1549 removeMouseListener(getPopupManager().getMouseHook());
1550 }
1551 }
1552
1553 popupEnabled = b;
1554 firePropertyChange("popupEnabled", !b, b);
1555 }
1556
1557
1558
1559
1560
1561
1562
1563 public void setTiltingEnabled(boolean b)
1564 {
1565 if (tiltingEnabled == b) {
1566 return;
1567 }
1568
1569 tiltingEnabled = b;
1570 firePropertyChange("tiltingEnabled", !b, b);
1571 }
1572
1573
1574
1575
1576
1577
1578
1579 public boolean isTiltingEnabled()
1580 {
1581 return tiltingEnabled;
1582 }
1583
1584
1585
1586
1587
1588
1589
1590 public void removeSetListener(SetListener listener)
1591 {
1592 listenerList.remove(SetListener.class, listener);
1593 }
1594
1595
1596
1597
1598
1599 public void repaint()
1600 {
1601 if (painting) {
1602 return;
1603 }
1604
1605 super.repaint();
1606 }
1607
1608
1609
1610
1611 public void synchronize()
1612 {
1613 setUserValue(getValue());
1614 }
1615
1616
1617
1618
1619
1620
1621 protected void notifyListeners(double newValue)
1622 {
1623 SetEvent e = new SetEvent(this, newValue);
1624 SetListener[] list = listenerList.getListeners(SetListener.class);
1625
1626 for (int i = 0; i < list.length; i++) {
1627 list[i].setPerformed(e);
1628 }
1629 }
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642 protected void paintComponent(Graphics arg0)
1643 {
1644 if (painting) {
1645 return;
1646 }
1647
1648 painting = true;
1649
1650 arg0.setColor(getBackground());
1651 arg0.fillRect(0, 0, getWidth(), getHeight());
1652
1653 Graphics2D g2d = (Graphics2D)arg0;
1654 renderer.initialize(g2d);
1655 renderer.paintTicks(g2d);
1656 renderer.paintKnob(g2d);
1657 renderer.paintMarker(g2d);
1658 renderer.paintTitleLabel(g2d);
1659 renderer.paintValueLabel(g2d);
1660
1661 painting = false;
1662
1663 }
1664
1665 private MouseHandler getMouseHandler()
1666 {
1667 if (mouseHandler == null) {
1668 mouseHandler = new MouseHandler();
1669 }
1670
1671 return mouseHandler;
1672 }
1673
1674 private TiltHandler getTiltHandler()
1675 {
1676 if (tiltHandler == null) {
1677 tiltHandler = new TiltHandler();
1678 }
1679
1680 return tiltHandler;
1681 }
1682
1683
1684
1685
1686
1687
1688 public void setValuePolicy(RangedValuePolicy p) {
1689 RangedValuePolicy oldValue = getValuePolicy();
1690 rangedValue.removePolicy(policy);
1691 this.policy = p;
1692 rangedValue.addPolicy(p);
1693 firePropertyChange("valuePolicy", oldValue, p);
1694 }
1695
1696
1697
1698
1699
1700
1701 public RangedValuePolicy getValuePolicy() {
1702 return policy;
1703 }
1704
1705
1706
1707
1708
1709
1710 protected RangedValueController getRangedValue() {
1711 return rangedValue;
1712 }
1713
1714
1715
1716
1717
1718
1719 protected RangedValueController getUserRangedValue() {
1720 return userRangedValue;
1721 }
1722
1723
1724
1725
1726
1727
1728 public boolean isUnitsVisible() {
1729 return unitsVisible;
1730 }
1731
1732
1733
1734
1735
1736
1737 public void setUnitsVisible(boolean b) {
1738 if (unitsVisible==b) return;
1739 boolean oldB = unitsVisible;
1740 unitsVisible = b;
1741 firePropertyChange("unitsVisible",oldB,b);
1742 repaint();
1743 }
1744
1745
1746
1747
1748
1749
1750 public Color getAlarmColor() {
1751 return alarmColor;
1752 }
1753
1754
1755
1756
1757
1758
1759 public void setAlarmColor(Color alarmColor) {
1760 Color oldValue = getAlarmColor();
1761 this.alarmColor = alarmColor;
1762 firePropertyChange("alarmColor", oldValue, alarmColor);
1763 }
1764
1765
1766
1767
1768
1769
1770 public double getHighAlarmLimit() {
1771 return highAlarmLimit;
1772 }
1773
1774
1775
1776
1777
1778
1779 public void setHighAlarmLimit(double highAlarmLimit) {
1780 double oldValue = getHighAlarmLimit();
1781 this.highAlarmLimit = highAlarmLimit;
1782 firePropertyChange("highAlarmLimir", oldValue, this.highAlarmLimit);
1783 }
1784
1785
1786
1787
1788
1789
1790 public double getHighWarningLimit() {
1791 return highWarningLimit;
1792 }
1793
1794
1795
1796
1797
1798
1799 public void setHighWarningLimit(double highWarningLimit) {
1800 double oldValue = getHighWarningLimit();
1801 this.highWarningLimit = highWarningLimit;
1802 firePropertyChange("highWarningLimit", oldValue, this.highWarningLimit);
1803 }
1804
1805
1806
1807
1808
1809
1810 public double getLowAlarmLimit() {
1811 return lowAlarmLimit;
1812 }
1813
1814
1815
1816
1817
1818
1819 public void setLowAlarmLimit(double lowAlarmLimit) {
1820 double oldValue = getLowAlarmLimit();
1821 this.lowAlarmLimit = lowAlarmLimit;
1822 firePropertyChange("lowAlarmLimit", oldValue, this.lowAlarmLimit);
1823 }
1824
1825
1826
1827
1828
1829
1830 public double getLowWarningLimit() {
1831 return lowWarningLimit;
1832 }
1833
1834
1835
1836
1837
1838
1839 public void setLowWarningLimit(double lowWarningLimit) {
1840 double oldValue = getLowWarningLimit();
1841 this.lowWarningLimit = lowWarningLimit;
1842 firePropertyChange("lowWarningLimit", oldValue, this.lowWarningLimit);
1843 }
1844
1845
1846
1847
1848
1849
1850 public Color getNormalColor() {
1851 return normalColor;
1852 }
1853
1854
1855
1856
1857
1858
1859 public void setNormalColor(Color normalColor) {
1860 Color oldValue = getNormalColor();
1861 this.normalColor = normalColor;
1862 firePropertyChange("normalColor", oldValue, this.normalColor);
1863 }
1864
1865
1866
1867
1868
1869
1870 public Color getOutOfBoundsColor() {
1871 return outOfBoundsColor;
1872 }
1873
1874
1875
1876
1877
1878
1879 public void setOutOfBoundsColor(Color outOfBoundsColor) {
1880 Color oldValue = getOutOfBoundsColor();
1881 this.outOfBoundsColor = outOfBoundsColor;
1882 firePropertyChange("outOfBoundsColor", oldValue, this.outOfBoundsColor);
1883 }
1884
1885
1886
1887
1888
1889
1890 public boolean isRangeColors() {
1891 return rangeColors;
1892 }
1893
1894
1895
1896
1897
1898
1899 public void setRangeColors(boolean rangeColors) {
1900 this.rangeColors = rangeColors;
1901 }
1902
1903
1904
1905
1906
1907
1908 public Color getWarningColor() {
1909 return warningColor;
1910 }
1911
1912
1913
1914
1915
1916
1917 public void setWarningColor(Color warningColor) {
1918 Color oldValue = getWarningColor();
1919 this.warningColor = warningColor;
1920 firePropertyChange("warningColor", oldValue, warningColor);
1921 }
1922
1923
1924
1925
1926 public boolean isDragArea(MouseEvent e) {
1927 return getMouseHandler().isMouseOutside(e);
1928 }
1929
1930
1931
1932
1933 @Override
1934 public void setTransferHandler(TransferHandler newHandler) {
1935 super.setTransferHandler(newHandler);
1936 if (newHandler instanceof CosyTransferHandler) {
1937 CosyTransferHandler t = (CosyTransferHandler) newHandler;
1938 t.addMouseFilter(this);
1939
1940 }
1941 }
1942
1943
1944
1945
1946
1947
1948
1949 public void setDragEnabled(boolean enabled) {
1950 if (isDragEnabled() == enabled) return;
1951 if (getTransferHandler() instanceof CosyTransferHandler) {
1952 if (((CosyTransferHandler)getTransferHandler()).isExportEnabled() == enabled) return;
1953
1954 ((CosyTransferHandler)getTransferHandler()).setExportEnabled(enabled, this);
1955 }
1956 firePropertyChange("dragEnabled", !enabled, enabled);
1957 }
1958
1959
1960
1961
1962
1963
1964 public boolean isDragEnabled() {
1965 if (getTransferHandler() instanceof CosyTransferHandler) {
1966 return ((CosyTransferHandler)getTransferHandler()).isExportEnabled();
1967 } else {
1968 return getTransferHandler() != null;
1969 }
1970 }
1971
1972
1973
1974
1975
1976
1977
1978 public void setDropEnabled(boolean enabled) {
1979 if (isDropEnabled() == enabled) return;
1980 if (getTransferHandler() instanceof CosyTransferHandler) {
1981 if (((CosyTransferHandler)getTransferHandler()).isReceiveEnabled() == enabled) return;
1982
1983 ((CosyTransferHandler)getTransferHandler()).setReceiveEnabled(enabled, this);
1984 }
1985 firePropertyChange("dropEnabled", !enabled, enabled);
1986 }
1987
1988
1989
1990
1991
1992
1993 public boolean isDropEnabled() {
1994 if (getTransferHandler() instanceof CosyTransferHandler) {
1995 return ((CosyTransferHandler)getTransferHandler()).isReceiveEnabled();
1996 } else {
1997 return getTransferHandler() != null;
1998 }
1999 }
2000
2001
2002
2003
2004
2005 @Override
2006 public void setBackground(Color bg) {
2007 super.setBackground(bg);
2008 getSyncButton().setBackground(bg);
2009 }
2010
2011
2012
2013
2014
2015 @Override
2016 public void setForeground(Color fg) {
2017 super.setForeground(fg);
2018 getSyncButton().setForeground(fg);
2019 }
2020
2021
2022
2023
2024
2025
2026 public boolean isAutoSynchronize() {
2027 return autoSynchronize;
2028 }
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039 public void setAutoSynchronize(boolean autoSynchronize) {
2040 if(isAutoSynchronize() == autoSynchronize) return;
2041 this.autoSynchronize = autoSynchronize;
2042 allowAutoSync = true;
2043 if (autoSynchronize) {
2044 getAutoSyncTimer().restart();
2045 } else {
2046 getAutoSyncTimer().stop();
2047 }
2048 firePropertyChange("autoSynchronize", !autoSynchronize, autoSynchronize);
2049 }
2050
2051 private javax.swing.Timer autoSyncTimer;
2052 private javax.swing.Timer getAutoSyncTimer() {
2053 if (autoSyncTimer == null) {
2054 autoSyncTimer = new javax.swing.Timer((int)autoSynchronizeDelay, new ActionListener(){
2055 public void actionPerformed(ActionEvent e) {
2056 if (allowAutoSync)
2057 synchronize();
2058 autoSyncTimer.stop();
2059 }
2060 });
2061
2062
2063 }
2064
2065 return autoSyncTimer;
2066 }
2067
2068
2069
2070
2071
2072
2073
2074 public long getAutoSynchronizeDelay() {
2075 return autoSynchronizeDelay;
2076 }
2077
2078
2079
2080
2081
2082
2083
2084 public void setAutoSynchronizeDelay(long autoSynchronizeDelay) {
2085 long oldValue = getAutoSynchronizeDelay();
2086 this.autoSynchronizeDelay = autoSynchronizeDelay;
2087
2088 getAutoSyncTimer().setDelay((int) autoSynchronizeDelay);
2089 getAutoSyncTimer().setInitialDelay((int) autoSynchronizeDelay);
2090 allowAutoSync=true;
2091 if (autoSynchronize) {
2092 getAutoSyncTimer().restart();
2093 } else {
2094 getAutoSyncTimer().stop();
2095 }
2096 firePropertyChange("autoSynchronizeDelay", oldValue, this.autoSynchronizeDelay);
2097
2098 }
2099
2100
2101
2102
2103
2104
2105 public static void main(String[] args)
2106 {
2107 final DialKnob knob = new DialKnob("Voltage");
2108
2109 Thread t = new Thread() {
2110 private double value;
2111 private double initValue;
2112 private long timeLastChanged = System.currentTimeMillis();
2113
2114 public void run()
2115 {
2116 JFrame frame = new javax.swing.JFrame("DialKnob");
2117 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
2118
2119 JPanel panel = new JPanel();
2120 frame.setContentPane(panel);
2121 frame.setSize(300, 300);
2122 knob.setTitleVisible(true);
2123 knob.setFormat("%d");
2124 knob.setUnits("V");
2125 knob.setPopupEnabled(true);
2126 knob.setEditable(true);
2127 knob.addSetListener(new SetAdapter() {
2128 public void setPerformed(SetEvent se)
2129 {
2130 timeLastChanged = System.currentTimeMillis();
2131 initValue = value;
2132
2133
2134 }
2135 });
2136 panel.setLayout(new java.awt.CardLayout());
2137 panel.add(knob, "DialKnob");
2138 frame.setVisible(true);
2139
2140 initValue = value = knob.getUserValue();
2141
2142 double relaxTime = 50;
2143
2144
2145 while (true) {
2146 value = knob.getUserValue()
2147 + (initValue - knob.getUserValue()) * Math.exp(-(System
2148 .currentTimeMillis() - timeLastChanged) / relaxTime);
2149 knob.setValue(value);
2150 System.out.println(value);
2151 try {
2152 sleep(10);
2153 } catch (Exception e) {
2154 }
2155 }
2156 }
2157 };
2158
2159 t.run();
2160
2161 }
2162 }
2163
2164