KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > swing > JArcDial


1 package JSci.swing;
2
3 import java.awt.*;
4 import java.awt.geom.*;
5 import java.awt.event.*;
6 import javax.swing.*;
7 import javax.swing.event.*;
8 import java.text.*;
9 import java.util.*;
10
11 /** A round dial, where the pointer can rotate many turns; the turns are indicated
12     by digits inside the dial. JPointer s must be added. */

13 public class JArcDial extends JPanel {
14
15     private double oneTurn;
16     private double zero;
17     private double startValue;
18     private double endValue;
19     private double startAngle = -2*Math.PI/6;
20     private double endAngle = 2*Math.PI/6;
21     // form of the bounding box
22
private double ha;
23     private double hb;
24     private double va;
25     private double vb;
26     private double minorTic = 5;
27     private double majorTic = 20;
28     private boolean setPaintMinorTicks = true;
29     private boolean setPaintMajorTicks = true;
30     private boolean setPaintLabels = true;
31     private double radius = 70;
32     private ArrayList pointers = new ArrayList();
33     private ChangeListener changeListener = new ChangeListener() {
34         public void stateChanged(ChangeEvent event) {
35         repaint();
36         }
37     };
38
39     /** constructs a dial with no pointers; the pointers will move
40      * inside a given range.
41      * @param start starting value of the dial
42      * @param end end value of the dial
43      */

44     public JArcDial(double start,double end) {
45     startValue=start;
46     endValue=end;
47     oneTurn = (endValue-startValue)*2.0*Math.PI/(endAngle-startAngle);
48     zero = startAngle-2.0*Math.PI*startValue/oneTurn;
49     setArc(-2*Math.PI/6,2*Math.PI/6);
50     setSize((int)(2*radius),(int)(2*radius));
51     addMouseListener(new TheMouseListener());
52     addMouseMotionListener(new TheMouseMotionListener());
53     }
54
55     /** Define the positions at which the the dial scale will start and stop.
56      * The angles must be such that stop>start.
57      * Counter-clockwise dials can be created by inverting the start and stop values
58      * (not angles!) in the constructor.
59      * @param start the angle (from the top, clockwise, in rads) where the
60      * scale start
61      * @param stop the angle (from the top, clockwise, in rads) where the
62      * scale will end
63      */

64     public void setArc(double start,double stop) {
65     if (start>stop) { throw new IllegalArgumentException JavaDoc("start angle >stop angle"); }
66     startAngle = start;
67     endAngle = stop;
68     oneTurn = (endValue-startValue)*2.0*Math.PI/(endAngle-startAngle);
69     zero = startAngle-2.0*Math.PI*startValue/oneTurn;
70
71     double f;
72
73     f=-Math.PI/2+2.0*Math.PI*Math.round(start);
74     while (f>start) f-=2.0*Math.PI;while (f<start) f+=2.0*Math.PI;
75     if (f<stop) ha=1.0;
76     else ha=Math.max(-Math.sin(start)+0.1,-Math.sin(stop)+0.1);
77
78     f=Math.PI/2+2.0*Math.PI*Math.round(start);
79     while (f>start) f-=2.0*Math.PI;while (f<start) f+=2.0*Math.PI;
80     if (f<stop) hb=1.0;
81     else hb=Math.max(Math.sin(start)+0.1,Math.sin(stop)+0.1);
82
83     f=2.0*Math.PI*Math.round(start);
84     while (f>start) f-=2.0*Math.PI;while (f<start) f+=2.0*Math.PI;
85     if (f<stop) va=1.0;
86     else va=Math.max(Math.cos(start)+0.1,Math.cos(stop)+0.1);
87
88     f=Math.PI+2.0*Math.PI*Math.round(start);
89     while (f>start) f-=2.0*Math.PI;while (f<start) f+=2.0*Math.PI;
90     if (f<stop) vb=1.0;
91     else vb=Math.max(-Math.cos(start)+0.1,-Math.cos(stop)+0.1);
92
93     setSize((int)((ha+hb)*radius),(int)((va+vb)*radius));
94     repaint();
95     }
96
97     /** as described in java.awt.Component */
98     public void setSize(int w,int h) {
99     super.setSize(w,h);
100     radius = Math.min(w/(ha+hb),h/(va+vb));
101     updateMinorTics();
102     updateMajorTics();
103     repaint();
104     }
105
106     /** as described in java.awt.Component */
107     public void setSize(Dimension d) { super.setSize(d); setSize((int)d.getWidth(),(int)d.getHeight()); }
108     
109     /** as described in java.awt.Component */
110     public Dimension getPreferredSize() { return new Dimension((int)((ha+hb)*radius),(int)((va+vb)*radius)); }
111
112     /** set the spacing between minor tics
113      * @param s the spacing between minor tics
114      */

115     public void setMinorTickSpacing(double s) {
116     minorTic = s;
117     updateMinorTics();
118     repaint();
119     }
120
121     /** set the spacing between major tics
122      * @param s the spacing between major tics
123      */

124     public void setMajorTickSpacing(double s) {
125     majorTic = s;
126     updateMajorTics();
127     repaint();
128     }
129
130     /** show the minor tics?
131      * @param b show the minor tics?
132      */

133     public void setPaintMinorTicks(boolean b) {
134     setPaintMinorTicks = b;
135     repaint();
136     }
137
138     /** show the major tics?
139      * @param b show the major tics?
140      */

141     public void setPaintMajorTicks(boolean b) {
142     setPaintMajorTicks = b;
143     repaint();
144     }
145
146     /** show the tic labels?
147      * @param b show the tic labels?
148      */

149     public void setPaintLabels(boolean b) {
150     setPaintLabels = b;
151     repaint();
152     }
153
154     private Line2D [] minorTics = null;
155     private Line2D [] majorTics = null;
156     private Point2D [] ticLabelPos = null;
157     private String JavaDoc [] ticLabelText = null;
158     private static NumberFormat formatter;
159     static {
160     formatter = NumberFormat.getNumberInstance();
161     formatter.setMaximumFractionDigits(2);
162     formatter.setMaximumIntegerDigits(3);
163     }
164
165     private void updateMinorTics() {
166     int N =(int)Math.abs((endValue-startValue)/minorTic);
167     double from = (startValue<endValue)?startValue:endValue;
168     minorTics = new Line2D[N];
169     for (int j=0;j<N;j++)
170         minorTics[j] =
171         new Line2D.Double(
172                   radius+radius*0.65*Math.sin(zero+2.0*Math.PI*(from+j*minorTic)/oneTurn),
173                   radius-radius*0.65*Math.cos(zero+2.0*Math.PI*(from+j*minorTic)/oneTurn),
174                   radius+radius*0.75*Math.sin(zero+2.0*Math.PI*(from+j*minorTic)/oneTurn),
175                   radius-radius*0.75*Math.cos(zero+2.0*Math.PI*(from+j*minorTic)/oneTurn)
176                   );
177     }
178
179     private void updateMajorTics() {
180     int N =(int)Math.abs((endValue-startValue)/majorTic)+1;
181     double from = (startValue<endValue)?startValue:endValue;
182     majorTics = new Line2D[N];
183     ticLabelPos = new Point2D[N];
184     ticLabelText = new String JavaDoc[N];
185     for (int j=0;j<N;j++) {
186         majorTics[j] =
187         new Line2D.Double(
188                   radius+radius*0.65*Math.sin(zero+2.0*Math.PI*(from+j*majorTic)/oneTurn),
189                   radius-radius*0.65*Math.cos(zero+2.0*Math.PI*(from+j*majorTic)/oneTurn),
190                   radius+radius*0.8*Math.sin(zero+2.0*Math.PI*(from+j*majorTic)/oneTurn),
191                   radius-radius*0.8*Math.cos(zero+2.0*Math.PI*(from+j*majorTic)/oneTurn)
192                   );
193         ticLabelText[j] = formatter.format(from+j*majorTic);
194         ticLabelPos[j] =
195         new Point2D.Double(
196                    radius+radius*0.9*Math.sin(zero+2.0*Math.PI*(from+j*majorTic)/oneTurn)
197                    -ticLabelText[j].length()*3,
198                    radius-radius*0.9*Math.cos(zero+2.0*Math.PI*(from+j*majorTic)/oneTurn)
199                    +6
200                    );
201     }
202
203     }
204
205
206     /** draw the component - don't call this directly, but use repaint() */
207     public void paintComponent(Graphics g) {
208     super.paintComponent(g);
209     Graphics2D g2 = (Graphics2D)g;
210     //g2.draw(new Ellipse2D.Double(0,0,2*radius,2*radius));
211
if (setPaintMinorTicks)
212         for (int j=0;j<minorTics.length;j++)
213         g2.draw(minorTics[j]);
214     if (setPaintMajorTicks)
215         for (int j=0;j<majorTics.length;j++)
216         g2.draw(majorTics[j]);
217     if (setPaintLabels)
218         for (int j=0;j<majorTics.length;j++)
219         g2.drawString(ticLabelText[j],(int)ticLabelPos[j].getX(),(int)ticLabelPos[j].getY());
220     Color saveColor = g2.getColor();
221     for (int j=0;j<pointers.size();j++)
222         ((JPointer)pointers.get(j)).paintOnDial(g2,radius,oneTurn,zero,radius*ha,radius*va);
223     g2.setColor(saveColor);
224     g2.fill(new Ellipse2D.Double(radius-3.0,radius-3.0,6.0,6.0));
225     }
226
227     /** add a pointer; it will be the actual component that contains informations
228      * @param p the pointer that must be added
229      */

230     public void addJPointer(JPointer p) {
231     for (int j=0;j<pointers.size();j++) if (pointers.get(j).equals(p)) return;
232     pointers.add(p);
233     p.addChangeListener(changeListener);
234     repaint();
235     }
236
237     /** remove a pointer; it should have been added with addJPointer()
238      * @param p the pointer that must be removed
239      */

240     public void removeJPointer(JPointer p) {
241     int j=0;
242     while (j<pointers.size()) {
243         if (pointers.get(j).equals(p)) pointers.remove(j);
244         else j++;
245     }
246     p.removeChangeListener(changeListener);
247     repaint();
248     }
249
250     // Mouse listeners
251

252     private JPointer dragged = null;
253     private double dragDelta;
254     private double theta(MouseEvent e) { return Math.atan2(e.getX()-radius,-(e.getY()-radius)); }
255     private class TheMouseListener extends MouseAdapter {
256     public void mousePressed(MouseEvent e) {
257         for (int j=pointers.size()-1;j>=0;j--)
258         if (((JPointer)pointers.get(j)).contains(e.getPoint())) {
259             dragged=(JPointer)pointers.get(j);
260             dragDelta=2.0*Math.PI*dragged.getValue()/oneTurn-theta(e);
261             dragged.setAdjusting(true);
262             break;
263         }
264     }
265     public void mouseReleased(MouseEvent e) {
266         if (dragged!=null) dragged.setAdjusting(false);
267         dragged = null;
268         boolean inside = false;
269         for (int j=0;j<pointers.size();j++)
270         if (((JPointer)pointers.get(j)).contains(e.getPoint())) {
271             inside=true;
272             break;
273         }
274         if (inside) setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
275         else setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
276     }
277     }
278
279     private class TheMouseMotionListener extends MouseMotionAdapter {
280     public void mouseMoved(MouseEvent e) {
281         boolean inside = false;
282         for (int j=0;j<pointers.size();j++)
283         if (((JPointer)pointers.get(j)).contains(e.getPoint())) {
284             inside=true;
285             break;
286         }
287         if (inside) setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
288         else setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
289     }
290     public void mouseDragged(MouseEvent e) {
291         if (dragged!=null) {
292         double to = (theta(e)+dragDelta);
293         if (zero+to>endAngle) to=endAngle-zero;
294         if (zero+to<startAngle) to=startAngle-zero;
295         to*=oneTurn/2.0/Math.PI;
296         dragged.setValue(to);
297         repaint();
298         }
299     }
300     }
301
302
303
304     // Main
305

306     public static void main(String JavaDoc [] args) {
307     JFrame frm = new JFrame();
308     frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
309     JArcDial d = new JArcDial(90.0,10.0);
310     d.setArc(-4*Math.PI/6,Math.PI/6);
311     frm.getContentPane().add(d);
312     d.setSize(260,260);
313     frm.pack();
314     frm.show();
315     try { Thread.sleep(3000); } catch (InterruptedException JavaDoc e) {}
316     JPointer p = new JPointer(JPointer.POINTER_SIMPLE_QUADRANGLE);
317     p.setColor(Color.MAGENTA);
318     p.setValue(25.0);
319     d.addJPointer(p);
320     try { Thread.sleep(3000); } catch (InterruptedException JavaDoc e) {}
321     JPointer p1 = new JPointer(JPointer.POINTER_SIMPLE_TRIANGLE);
322     p1.setColor(Color.CYAN);
323     p1.setValue(75.0);
324     d.addJPointer(p1);
325         
326     p1.addChangeListener(new ChangeListener() {
327         public void stateChanged(ChangeEvent e) {
328             double v=((JPointer)e.getSource()).getValue();
329             System.out.println("State changed: "+v);
330         }
331         });
332
333     //try { Thread.sleep(3000); } catch (InterruptedException e) {}
334
//p.setValue(p.getValue()+10.0);
335
//try { Thread.sleep(3000); } catch (InterruptedException e) {}
336
//p.setValue(p.getValue()+10.0);
337
//try { Thread.sleep(3000); } catch (InterruptedException e) {}
338
//p.setValue(p.getValue()+10.0);
339
//try { Thread.sleep(3000); } catch (InterruptedException e) {}
340
//p.setValue(p.getValue()+10.0);
341

342     //try { Thread.sleep(3000); } catch (InterruptedException e) {}
343
//d.removeJPointer(p);
344
//try { Thread.sleep(3000); } catch (InterruptedException e) {}
345
//d.removeJPointer(p1);
346
//try { Thread.sleep(3000); } catch (InterruptedException e) {}
347
}
348
349
350     
351 }
352
Popular Tags