-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDial.java
199 lines (163 loc) · 6.33 KB
/
Dial.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
/**
* A Dial to be used in a Stopwatch
* Consists of a hand of a custom color
*/
public class Dial implements Icon {
private int size;
private boolean threeLevels;
private Color color;
private static final Color TICK_COLOR = Color.BLACK;
//location of this dial, set when draw() is called
private int x;
private int y;
/**
* Creates a dial of the given parameters
*
* @param size DIAMETER of the Dial
* @param threeLevels whether to paint the third level of ticks
* @param color of the hand
*/
public Dial(int size, boolean threeLevels, Color color) {
this.size = size;
this.threeLevels = threeLevels;
this.color = color;
}
/**
* @return the color of this Dial's hands
*/
public Color getColor() {
return this.color;
}
/**
* @return the height of this Dial
*/
public int getIconHeight() {
return this.size;
}
/**
* @return the width of this Dial
*/
public int getIconWidth() {
return this.size;
}
//x,y is 0,0 for larger one
//x,y is drawn in the middle for the smaller one
/**
* Paints this Dial with the given parameters
*
* @param c null okay
* @param g Graphics for painting
* @param x TOP LEFT X-coordinate location of the icon
* @param y TOP LEFT Y-coordinate location of the icon
*/
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g;
this.x = x;
this.y = y;
double radius = size / 2.0d;
// (Ax, Ay) represents the center of the circle
// the ticks are NOT drawn from this point
double Ax = x + size / 2.0d;
double Ay = y + size / 2.0d;
/*
Represents the outer endpoint of each tick (the tick ends here)
(along the circle of the clock)
*/
double Bx, By;
// Represents the inner endpoint of each tick (the tick starts here)
double Cx = 0, Cy = 0;
g2.setColor(TICK_COLOR);
//LEVEL 1 & 2 ticks
for (int deg = 0; deg < 360; deg += 6) {
double angle = Math.toRadians(deg); //angle in radians
double cosine = Math.cos(angle);
double sine = Math.sin(angle);
Bx = (radius * cosine) + Ax;
By = (radius * sine) + Ay;
if (deg % 30 == 0) { //LEVEL 1 ticks
Cx = (0.82 * radius * cosine) + Ax;
Cy = (0.82 * radius * sine) + Ay;
g2.draw(new Line2D.Double(Cx, Cy, Bx, By));
} else if (deg % 6 == 0) { //LEVEL 2 ticks
Cx = (0.89 * radius * cosine) + Ax;
Cy = (0.89 * radius * sine) + Ay;
g2.draw(new Line2D.Double(Cx, Cy, Bx, By));
}
}
// LEVEL 3 ticks
if (this.threeLevels) {
for (double deg = 0; deg < 360; deg += 1.2d) {
double angle = Math.toRadians(deg); //angle in radians
double cosine = Math.cos(angle);
double sine = Math.sin(angle);
Bx = (radius * cosine) + Ax;
By = (radius * sine) + Ay;
Cx = (0.95 * radius * cosine) + Ax;
Cy = (0.95 * radius * sine) + Ay;
g2.draw(new Line2D.Double(Cx, Cy, Bx, By));
}
}
// draw the number labels
for (int i = 0; i < 12; i++) {
int deg = i * 30 - 90;
double angle = Math.toRadians(deg); //angle in radians
double cosine = Math.cos(angle);
double sine = Math.sin(angle);
MultiLineString mMLS = new MultiLineString();
mMLS.setText(Integer.toString(i * 5));
if (this.threeLevels) {
// (Bx, By) represents where we want to print the label
Bx = (0.74 * radius * cosine) + Ax;
By = (0.74 * radius * sine) + Ay;
mMLS.setSize(MultiLineString.LARGE);
Rectangle2D bounds = mMLS.getBounds(g2);
int wd = (int) bounds.getWidth();
int ht = (int) bounds.getHeight();
mMLS.draw(g2, new Rectangle2D.Double(Bx - (wd * 0.5d), By - (ht * 0.5d), wd, ht));
} else {
// (Bx, By) represents where we want to print the label
Bx = (0.67 * radius * cosine) + Ax;
By = (0.67 * radius * sine) + Ay;
mMLS.setSize(MultiLineString.SMALL);
Rectangle2D bounds = mMLS.getBounds(g2);
int wd = (int) bounds.getWidth();
int ht = (int) bounds.getHeight();
mMLS.draw(g2, new Rectangle2D.Double(Bx - (wd * 0.5d), By - (ht * 0.5d), wd, ht));
}
}
}
/**
* Draws the Dial's hand to represent the current Degree
*
* @param angleDeg in DEGREES where 0 is RIGHT, 90 is DOWN
* @param g2 Graphics2D reference used for drawing
*/
public void setAngle(double angleDeg, Graphics2D g2) {
double angleRad = Math.toRadians(angleDeg);
double radius = size / 2.0d;
double Ax = x + size / 2.0d;
double Ay = y + size / 2.0d;
double Bx, By; //represents the endpoint of the arrow
Bx = 0.95 * radius * Math.cos(angleRad) + Ax;
By = 0.95 * radius * Math.sin(angleRad) + Ay;
/*
The following logic of code that is used to draw the arrows
is inspired by the work of Cay Horstmann in the program
Violet - A program for editing UML diagrams
*/
final double ARROW_TIP_ANGLE = Math.PI / 8;
final double ARROW_TIP_LENGTH = radius * 0.08d; //should depend on size
double x1 = Bx - ARROW_TIP_LENGTH * Math.cos(angleRad + ARROW_TIP_ANGLE);
double y1 = By - ARROW_TIP_LENGTH * Math.sin(angleRad + ARROW_TIP_ANGLE);
double x2 = Bx - ARROW_TIP_LENGTH * Math.cos(angleRad - ARROW_TIP_ANGLE);
double y2 = By - ARROW_TIP_LENGTH * Math.sin(angleRad - ARROW_TIP_ANGLE);
g2.setColor(this.color);
g2.setStroke(new BasicStroke(1.4f));
g2.draw(new Line2D.Double(Ax, Ay, Bx, By));
g2.draw(new Line2D.Double(Bx, By, x1, y1));
g2.draw(new Line2D.Double(Bx, By, x2, y2));
}
}