diff --git a/src/app.rs b/src/app.rs index bc693e3..b8abcc0 100644 --- a/src/app.rs +++ b/src/app.rs @@ -57,6 +57,7 @@ pub struct AppArgs { pub current_value_pause: Duration, pub initial_value_countdown: Duration, pub current_value_countdown: Duration, + pub elapsed_value_countdown: Duration, pub current_value_timer: Duration, } @@ -80,6 +81,7 @@ impl From<(Args, AppStorage)> for AppArgs { initial_value_countdown: args.countdown.unwrap_or(stg.inital_value_countdown), // invalidate `current_value_countdown` if an initial value is set via args current_value_countdown: args.countdown.unwrap_or(stg.current_value_countdown), + elapsed_value_countdown: stg.elapsed_value_countdown, current_value_timer: stg.current_value_timer, } } @@ -104,6 +106,7 @@ impl App { current_value_work, current_value_pause, current_value_countdown, + elapsed_value_countdown, current_value_timer, content, with_decis, @@ -115,12 +118,15 @@ impl App { app_time: get_app_time(), style, with_decis, - countdown: CountdownState::new(ClockState::::new(ClockStateArgs { - initial_value: initial_value_countdown, - current_value: current_value_countdown, - tick_value: Duration::from_millis(TICK_VALUE_MS), - with_decis, - })), + countdown: CountdownState::new( + ClockState::::new(ClockStateArgs { + initial_value: initial_value_countdown, + current_value: current_value_countdown, + tick_value: Duration::from_millis(TICK_VALUE_MS), + with_decis, + }), + elapsed_value_countdown, + ), timer: TimerState::new(ClockState::::new(ClockStateArgs { initial_value: Duration::ZERO, current_value: current_value_timer, @@ -247,6 +253,7 @@ impl App { current_value_countdown: Duration::from( *self.countdown.get_clock().get_current_value(), ), + elapsed_value_countdown: Duration::from(*self.countdown.get_elapsed_value()), current_value_timer: Duration::from(*self.timer.get_clock().get_current_value()), } } diff --git a/src/storage.rs b/src/storage.rs index a805cfa..99a0c28 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -25,6 +25,7 @@ pub struct AppStorage { // countdown pub inital_value_countdown: Duration, pub current_value_countdown: Duration, + pub elapsed_value_countdown: Duration, // timer pub current_value_timer: Duration, } @@ -50,6 +51,7 @@ impl Default for AppStorage { // countdown inital_value_countdown: DEFAULT_COUNTDOWN, current_value_countdown: DEFAULT_COUNTDOWN, + elapsed_value_countdown: Duration::ZERO, // timer current_value_timer: Duration::ZERO, } diff --git a/src/widgets/clock.rs b/src/widgets/clock.rs index 759badb..08fad44 100644 --- a/src/widgets/clock.rs +++ b/src/widgets/clock.rs @@ -91,6 +91,27 @@ pub struct ClockStateArgs { } impl ClockState { + pub fn with_mode(mut self, mode: Mode) -> Self { + self.mode = mode; + self + } + + pub fn get_mode(&self) -> &Mode { + &self.mode + } + + pub fn is_initial(&self) -> bool { + self.mode == Mode::Initial + } + + pub fn run(&mut self) { + self.mode = Mode::Tick + } + + pub fn is_running(&self) -> bool { + self.mode == Mode::Tick + } + pub fn toggle_pause(&mut self) { self.mode = if self.mode == Mode::Tick { Mode::Pause @@ -185,6 +206,7 @@ impl ClockState { }; self.update_format(); } + pub fn edit_current_down(&mut self) { self.current_value = match self.mode { Mode::Editable(Time::Decis, _) => { @@ -203,22 +225,6 @@ impl ClockState { self.update_mode(); } - pub fn get_mode(&self) -> &Mode { - &self.mode - } - - pub fn run(&mut self) { - self.mode = Mode::Tick - } - - pub fn is_running(&self) -> bool { - self.mode == Mode::Tick - } - - pub fn is_initial(&self) -> bool { - self.mode == Mode::Initial - } - pub fn is_edit_mode(&self) -> bool { matches!(self.mode, Mode::Editable(_, _)) } diff --git a/src/widgets/countdown.rs b/src/widgets/countdown.rs index 967b890..4f869e0 100644 --- a/src/widgets/countdown.rs +++ b/src/widgets/countdown.rs @@ -10,9 +10,10 @@ use std::{cmp::max, time::Duration}; use crate::{ common::Style, constants::TICK_VALUE_MS, + duration::DurationEx, events::{Event, EventHandler}, utils::center, - widgets::clock::{self, ClockState, ClockStateArgs, ClockWidget}, + widgets::clock::{self, ClockState, ClockStateArgs, ClockWidget, Mode as ClockMode}, }; /// State for Countdown Widget @@ -20,26 +21,34 @@ use crate::{ pub struct CountdownState { /// clock to count down clock: ClockState, - /// clock to count up afterwards - timer: ClockState, + /// clock to count time after `DONE` - similar to Mission Elapsed Time (MET) + elapsed_clock: ClockState, } impl CountdownState { - pub fn new(clock: ClockState) -> Self { + pub fn new(clock: ClockState, elapsed_value: Duration) -> Self { Self { clock, - timer: ClockState::::new(ClockStateArgs { + elapsed_clock: ClockState::::new(ClockStateArgs { initial_value: Duration::ZERO, - current_value: Duration::ZERO, + current_value: elapsed_value, tick_value: Duration::from_millis(TICK_VALUE_MS), with_decis: false, + }) + // A previous `elapsed_value > 0` means the `Clock` was running before, + // but not in `Initial` state anymore. Updating `Mode` here + // is needed to handle `Event::Tick` in `EventHandler::update` properly + .with_mode(if elapsed_value.gt(&Duration::ZERO) { + ClockMode::Pause + } else { + ClockMode::Initial }), } } pub fn set_with_decis(&mut self, with_decis: bool) { self.clock.with_decis = with_decis; - self.timer.with_decis = with_decis; + self.elapsed_clock.with_decis = with_decis; } pub fn get_clock(&self) -> &ClockState { @@ -47,7 +56,11 @@ impl CountdownState { } pub fn is_running(&self) -> bool { - self.clock.is_running() || self.timer.is_running() + self.clock.is_running() || self.elapsed_clock.is_running() + } + + pub fn get_elapsed_value(&self) -> &DurationEx { + self.elapsed_clock.get_current_value() } } @@ -59,9 +72,9 @@ impl EventHandler for CountdownState { if !self.clock.is_done() { self.clock.tick(); } else { - self.timer.tick(); - if self.timer.is_initial() { - self.timer.run(); + self.elapsed_clock.tick(); + if self.elapsed_clock.is_initial() { + self.elapsed_clock.run(); } } } @@ -69,21 +82,21 @@ impl EventHandler for CountdownState { KeyCode::Char('r') => { // reset both clocks self.clock.reset(); - self.timer.reset(); + self.elapsed_clock.reset(); } KeyCode::Char('s') => { - // toggle pause status depending on who is running + // toggle pause status depending on which clock is running if !self.clock.is_done() { self.clock.toggle_pause(); } else { - self.timer.toggle_pause(); + self.elapsed_clock.toggle_pause(); } } KeyCode::Char('e') => { self.clock.toggle_edit(); // stop + reset timer entering `edit` mode - if self.timer.is_running() { - self.timer.toggle_pause(); + if self.elapsed_clock.is_running() { + self.elapsed_clock.toggle_pause(); } } KeyCode::Left if edit_mode => { @@ -94,13 +107,13 @@ impl EventHandler for CountdownState { } KeyCode::Up if edit_mode => { self.clock.edit_up(); - // whenever clock value is changed, reset timer - self.timer.reset(); + // whenever `clock`'s value is changed, reset `elapsed_clock` + self.elapsed_clock.reset(); } KeyCode::Down if edit_mode => { self.clock.edit_down(); // whenever clock value is changed, reset timer - self.timer.reset(); + self.elapsed_clock.reset(); } _ => return Some(event), }, @@ -125,13 +138,16 @@ impl StatefulWidget for Countdown { format!( "Countdown {} +{}", state.clock.get_mode(), - state.timer.get_current_value().to_string_with_decis() + state + .elapsed_clock + .get_current_value() + .to_string_with_decis() ) } else { format!( "Countdown {} +{}", state.clock.get_mode(), - state.timer.get_current_value() + state.elapsed_clock.get_current_value() ) } } else {