From c7c5f7955f2d7364d24807552d887a3d109b03d8 Mon Sep 17 00:00:00 2001 From: Tianyi Shi Date: Fri, 9 Oct 2020 08:41:57 +0600 Subject: [PATCH] add new example: stopwatch (#503) Co-authored-by: Mckol --- Readme.md | 1 + examples/src/bin/stopwatch.rs | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 examples/src/bin/stopwatch.rs diff --git a/Readme.md b/Readme.md index 0388184..bb3c040 100644 --- a/Readme.md +++ b/Readme.md @@ -94,6 +94,7 @@ Here are some cool applications using cursive: * [fui](https://github.com/xliiv/fui): Add CLI & form interface to your program. * [grin-tui](https://github.com/mimblewimble/grin): Minimal implementation of the MimbleWimble protocol. * [ripasso](https://github.com/cortex/ripasso): A simple password manager written in Rust. +* [clock-cli](https://github.com/TianyiShi2001/clock-cli-rs): A clock with stopwatch and countdown timer functionalities * [sudoku-tui](https://github.com/TianyiShi2001/sudoku-tui): Play sudoku on the command line. ## Goals diff --git a/examples/src/bin/stopwatch.rs b/examples/src/bin/stopwatch.rs new file mode 100644 index 0000000..46159e6 --- /dev/null +++ b/examples/src/bin/stopwatch.rs @@ -0,0 +1,91 @@ +//! A simple stopwatch implementation. +//! Also check out `clock-cli` (https://github.com/TianyiShi2001/cl!ock-cli-rs), +//! which aims to implement a fully-fledged clock with stopwatch, countdown +//! timer, and possibly more functionalities. + +use cursive::traits::{Nameable, Resizable}; +use cursive::views::{Button, Canvas, Dialog, LinearLayout}; +use std::time::{Duration, Instant}; + +fn main() { + let mut siv = cursive::default(); + + siv.add_layer( + Dialog::new() + .title("Stopwatch") + .content( + LinearLayout::horizontal() + .child( + Canvas::new(Watch { + last_started: Instant::now(), + last_elapsed: Duration::default(), + running: true, + }) + .with_draw(|s, printer| { + printer.print( + (0, 1), + &format!("{:.2?}", s.elapsed()), + ); + }) + .with_name("stopwatch") + .fixed_size((8, 3)), + ) + .child( + LinearLayout::vertical() + .child(Button::new("Start", run(Watch::start))) + .child(Button::new("Pause", run(Watch::pause))) + .child(Button::new("Stop", run(Watch::stop))), + ), + ) + .button("Quit", |s| s.quit()) + .h_align(cursive::align::HAlign::Center), + ); + + siv.set_fps(20); + + siv.run(); +} + +struct Watch { + last_started: Instant, + last_elapsed: Duration, + running: bool, +} + +impl Watch { + fn start(&mut self) { + self.running = true; + self.last_started = Instant::now(); + } + + fn elapsed(&self) -> Duration { + self.last_elapsed + + if self.running { + Instant::now() - self.last_started + } else { + Duration::default() + } + } + + fn pause(&mut self) { + self.last_elapsed = self.elapsed(); + self.running = false; + } + + fn stop(&mut self) { + self.running = false; + self.last_elapsed = Duration::default(); + } +} + +// Helper function to find the stopwatch view and run a closure on it. +fn run(f: F) -> impl Fn(&mut cursive::Cursive) +where + F: Fn(&mut Watch), +{ + move |s| { + s.call_on_name("stopwatch", |c: &mut Canvas| { + f(c.state_mut()); + }); + } +}