-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStopwatch.java
115 lines (99 loc) · 3.43 KB
/
Stopwatch.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
import java.awt.*;
import java.time.*;
/**
* A Stopwatch that keeps track of time up to 60 hours
*/
public class Stopwatch implements MoveableShape {
private int radius;
private boolean running;
private boolean frozenDisp;
private Instant startInstant;
private Instant pauseInstant;
private long pausedMillis;
private long totalMillis;
private Dial secDial;
private Dial minDial;
private double secsDisp;
private double minsDisp;
/**
* Creates a new Stopwatch with the supplied radius
*
* @param radius of the larger dial
*/
public Stopwatch(int radius) {
this.radius = radius;
this.running = false;
this.frozenDisp = false;
this.startInstant = null;
this.secDial = new Dial(radius * 2, true, Color.RED);
this.minDial = new Dial((int) (radius * 0.8), false, Color.BLUE);
}
/**
* Simulates the top button being pressed of a stopwatch
* Namely, it pauses or resumes the stopwatch
*/
public void topButtonPressed() {
if (startInstant == null) //starting from a reset state
startInstant = Instant.now();
else if (running) //running, we need to pause
this.pauseInstant = Instant.now();
else if (!running) { //paused, now resuming
pausedMillis += Duration.between(pauseInstant, Instant.now()).toMillis();
pauseInstant = null;
}
this.running = !this.running;
}
/**
* Simulates the second button being pressed of a stopwatch
* Namely, if the watch is paused, it will be reset.
* Otherwise, the display will freeze
*/
public void secondButtonPressed() {
if (this.running && this.frozenDisp)
this.frozenDisp = false;
else if (this.running && !this.frozenDisp)
this.frozenDisp = true;
else if (!this.running) { // RESET
this.running = false;
this.frozenDisp = false;
this.startInstant = null;
this.pausedMillis = 0;
this.totalMillis = 0;
this.secsDisp = 0;
this.minsDisp = 0;
}
}
/**
* Updates the time of this stopwatch object
* Accounts for all time frozen
* This method does nothing if the watch is frozen or not running
*/
@Override
public void move() {
if (running && !frozenDisp) {
//total number of seconds
this.totalMillis = Duration.between(startInstant, Instant.now()).toMillis();
long runningMillis = totalMillis - pausedMillis;
double secs = (double) runningMillis / 1000.0d;
double mins = ((secs / 60.0d) % 60);
secs %= 60; //mins and secs are now in range 0-60
this.minsDisp = mins;
this.secsDisp = secs % 60;
}
//else: NOT running --> do nothing
}
/**
* Updates the UI with the current time stored in this stopwatch object
* If the watch's current state is paused or frozen this method will
* appear to do nothing -- it is still redrawing the watch
*
* @param g2 Graphics2D used for drawing
*/
@Override
public void draw(Graphics2D g2) {
secDial.paintIcon(null, g2, 0, 0);
secDial.setAngle(this.secsDisp * 6 - 90, g2);
minDial.paintIcon(null, g2, (int) (radius * 0.6d), (int) (radius * 0.4d));
minDial.setAngle(this.minsDisp * 6 - 90, g2);
}
}