retris/
timer.rs

1use crate::numbers;
2use std::time::Instant;
3use cursive::{
4    View,
5    Printer,
6};
7
8pub struct Timer {
9    timer: Instant,
10    is_paused: bool,
11    pause_start: Instant,
12}
13
14impl Default for Timer {
15    fn default() -> Self {
16        Self::new()
17    }
18}
19
20impl Timer {
21    pub fn new() -> Self {
22        let now = Instant::now();
23        Self {
24            timer: now,
25            is_paused: false,
26            pause_start: now,
27        }
28    }
29
30    pub fn renew(&mut self) {
31        let now = Instant::now();
32        self.timer = now;
33        self.pause_start = now;
34        self.is_paused = false;
35    }
36
37    pub fn toggle_pause(&mut self) {
38        if self.is_paused {
39            self.timer += Instant::now() - self.pause_start;
40        } else {
41            self.pause_start = Instant::now();
42        }
43        self.is_paused = !self.is_paused;
44    }
45
46    pub fn reset(&mut self) {
47        let now = Instant::now();
48        self.timer = now;
49        self.pause_start = now;
50    }
51
52    pub fn time2str(&self) -> String {
53        let (mins, secs, mills) = self.elapsed();
54        let mins = numbers::padding(mins as usize, 2);
55        let secs = numbers::padding(secs as usize, 2);
56        let mills = numbers::padding(mills as usize, 3);
57        format!("Time {}:{}:{}", mins, secs, mills)
58    }
59
60    fn elapsed(&self) -> (u128, u128, u128) {
61        let mills = if self.is_paused {
62            (self.pause_start - self.timer).as_millis()
63        } else { self.timer.elapsed().as_millis() };
64        let mins = mills / 60000;
65        let secs = (mills % 60000) / 1000;
66        let mills = mills % 1000;
67        (mins, secs, mills)
68    }
69}
70
71impl View for Timer {
72    fn draw(&self, printer: &Printer) {
73        printer.print((0, 0), &self.time2str());
74    }
75
76    fn required_size(&mut self, _: cursive::Vec2) -> cursive::Vec2 {
77        let line = self.time2str();
78        cursive::Vec2::new(line.len() + 3, 1)
79    }
80}