improve format handling + fix days rendering (#107)
* render_(format) functions, compact `YyyDddHhMmSs` * compact rendering of other formats * add `YDHhMmSs`+`YDdHhMmSs` formats * tests for `YDHhMmSs`+`YDdHhMmSs` * `YyDHhMmSs` + `YyDdHhMmSs` * `YyyDHhMmSs` + `YyyDdHhMmSs` * fix `edit_up` to compare `years` properly and add `test_edit_up_overflow_protection` * fix rendering `Format::YyyDdHhMmSs`
This commit is contained in:
parent
40eb602953
commit
816741f842
@ -2,6 +2,3 @@ pub static APP_NAME: &str = env!("CARGO_PKG_NAME");
|
|||||||
|
|
||||||
pub static TICK_VALUE_MS: u64 = 1000 / 10; // 0.1 sec in milliseconds
|
pub static TICK_VALUE_MS: u64 = 1000 / 10; // 0.1 sec in milliseconds
|
||||||
pub static FPS_VALUE_MS: u64 = 1000 / 60; // 60 FPS in milliseconds
|
pub static FPS_VALUE_MS: u64 = 1000 / 60; // 60 FPS in milliseconds
|
||||||
|
|
||||||
pub static LABEL_DAYS: &str = "d";
|
|
||||||
pub static LABEL_YEARS: &str = "y";
|
|
||||||
|
|||||||
1613
src/widgets/clock.rs
1613
src/widgets/clock.rs
File diff suppressed because it is too large
Load Diff
@ -7,9 +7,13 @@ use ratatui::{
|
|||||||
pub const DIGIT_SIZE: usize = 5;
|
pub const DIGIT_SIZE: usize = 5;
|
||||||
pub const DIGIT_WIDTH: u16 = DIGIT_SIZE as u16;
|
pub const DIGIT_WIDTH: u16 = DIGIT_SIZE as u16;
|
||||||
pub const DIGIT_HEIGHT: u16 = DIGIT_SIZE as u16 + 1 /* border height */;
|
pub const DIGIT_HEIGHT: u16 = DIGIT_SIZE as u16 + 1 /* border height */;
|
||||||
|
pub const TWO_DIGITS_WIDTH: u16 = DIGIT_WIDTH + DIGIT_SPACE_WIDTH + DIGIT_WIDTH; // digit-space-digit
|
||||||
|
pub const THREE_DIGITS_WIDTH: u16 =
|
||||||
|
DIGIT_WIDTH + DIGIT_SPACE_WIDTH + DIGIT_WIDTH + DIGIT_SPACE_WIDTH + DIGIT_WIDTH; // digit-space-digit-space-digit
|
||||||
pub const COLON_WIDTH: u16 = 4; // incl. padding left + padding right
|
pub const COLON_WIDTH: u16 = 4; // incl. padding left + padding right
|
||||||
pub const DOT_WIDTH: u16 = 4; // incl. padding left + padding right
|
pub const DOT_WIDTH: u16 = 4; // incl. padding left + padding right
|
||||||
pub const DIGIT_SPACE_WIDTH: u16 = 1; // space between digits
|
pub const DIGIT_SPACE_WIDTH: u16 = 1; // space between digits
|
||||||
|
pub const DIGIT_LABEL_WIDTH: u16 = 3; // label (single char) incl. padding left + padding right
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const DIGIT_0: [u8; DIGIT_SIZE * DIGIT_SIZE] = [
|
const DIGIT_0: [u8; DIGIT_SIZE * DIGIT_SIZE] = [
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
common::ClockTypeId,
|
common::ClockTypeId,
|
||||||
duration::{ONE_DAY, ONE_DECI_SECOND, ONE_HOUR, ONE_MINUTE, ONE_SECOND, ONE_YEAR},
|
duration::{
|
||||||
|
MAX_DURATION, ONE_DAY, ONE_DECI_SECOND, ONE_HOUR, ONE_MINUTE, ONE_SECOND, ONE_YEAR,
|
||||||
|
},
|
||||||
widgets::clock::*,
|
widgets::clock::*,
|
||||||
};
|
};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -114,20 +116,44 @@ fn test_get_format_boundaries() {
|
|||||||
// DddHhMmSs
|
// DddHhMmSs
|
||||||
c.set_current_value((ONE_YEAR.saturating_sub(ONE_SECOND)).into());
|
c.set_current_value((ONE_YEAR.saturating_sub(ONE_SECOND)).into());
|
||||||
assert_eq!(c.get_format(), Format::DddHhMmSs);
|
assert_eq!(c.get_format(), Format::DddHhMmSs);
|
||||||
// YDddHhMmSs
|
// YDHhMmSs
|
||||||
c.set_current_value(ONE_YEAR.into());
|
c.set_current_value(ONE_YEAR.into());
|
||||||
|
assert_eq!(c.get_format(), Format::YDHhMmSs);
|
||||||
|
// YDdHhMmSs
|
||||||
|
c.set_current_value((ONE_YEAR + (100 * ONE_DAY).saturating_sub(ONE_SECOND)).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YDdHhMmSs);
|
||||||
|
// YDddHhMmSs
|
||||||
|
c.set_current_value((ONE_YEAR + 100 * ONE_DAY).into());
|
||||||
assert_eq!(c.get_format(), Format::YDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YDddHhMmSs);
|
||||||
// YDddHhMmSs
|
// YDddHhMmSs
|
||||||
c.set_current_value(((10 * ONE_YEAR).saturating_sub(ONE_SECOND)).into());
|
c.set_current_value(((10 * ONE_YEAR).saturating_sub(ONE_SECOND)).into());
|
||||||
assert_eq!(c.get_format(), Format::YDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YDddHhMmSs);
|
||||||
// YyDddHhMmSs
|
// YyDHhMmSs
|
||||||
c.set_current_value((10 * ONE_YEAR).into());
|
c.set_current_value((10 * ONE_YEAR).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyDHhMmSs);
|
||||||
|
// YyDdHhMmSs
|
||||||
|
c.set_current_value((10 * ONE_YEAR + 10 * ONE_DAY).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyDdHhMmSs);
|
||||||
|
// YyDdHhMmSs
|
||||||
|
c.set_current_value((10 * ONE_YEAR + (100 * ONE_DAY).saturating_sub(ONE_SECOND)).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyDdHhMmSs);
|
||||||
|
// YyDddHhMmSs
|
||||||
|
c.set_current_value((10 * ONE_YEAR + 100 * ONE_DAY).into());
|
||||||
assert_eq!(c.get_format(), Format::YyDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YyDddHhMmSs);
|
||||||
// YyDddHhMmSs
|
// YyDddHhMmSs
|
||||||
c.set_current_value(((100 * ONE_YEAR).saturating_sub(ONE_SECOND)).into());
|
c.set_current_value(((100 * ONE_YEAR).saturating_sub(ONE_SECOND)).into());
|
||||||
assert_eq!(c.get_format(), Format::YyDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YyDddHhMmSs);
|
||||||
// YyyDddHhMmSs
|
// YyyDHhMmSs
|
||||||
c.set_current_value((100 * ONE_YEAR).into());
|
c.set_current_value((100 * ONE_YEAR).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyyDHhMmSs);
|
||||||
|
// YyyDdHhMmSs
|
||||||
|
c.set_current_value((100 * ONE_YEAR + 10 * ONE_DAY).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyyDdHhMmSs);
|
||||||
|
// YyyDdHhMmSs
|
||||||
|
c.set_current_value((100 * ONE_YEAR + (100 * ONE_DAY).saturating_sub(ONE_SECOND)).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyyDdHhMmSs);
|
||||||
|
// YyyDddHhMmSs
|
||||||
|
c.set_current_value((100 * ONE_YEAR + 100 * ONE_DAY).into());
|
||||||
assert_eq!(c.get_format(), Format::YyyDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YyyDddHhMmSs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,13 +185,43 @@ fn test_get_format_years() {
|
|||||||
with_decis: false,
|
with_decis: false,
|
||||||
app_tx: None,
|
app_tx: None,
|
||||||
});
|
});
|
||||||
// YDddHhMmSs
|
// YDHhMmSs (1 year, 0 days)
|
||||||
|
assert_eq!(c.get_format(), Format::YDHhMmSs);
|
||||||
|
|
||||||
|
// YDHhMmSs (1 year, 1 day)
|
||||||
|
c.set_current_value((ONE_YEAR + ONE_DAY).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YDHhMmSs);
|
||||||
|
|
||||||
|
// YDdHhMmSs (1 year, 10 days)
|
||||||
|
c.set_current_value((ONE_YEAR + 10 * ONE_DAY).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YDdHhMmSs);
|
||||||
|
|
||||||
|
// YDddHhMmSs (1 year, 100 days)
|
||||||
|
c.set_current_value((ONE_YEAR + 100 * ONE_DAY).into());
|
||||||
assert_eq!(c.get_format(), Format::YDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YDddHhMmSs);
|
||||||
// YyDddHhMmSs
|
|
||||||
|
// YyDHhMmSs (10 years)
|
||||||
c.set_current_value((10 * ONE_YEAR).into());
|
c.set_current_value((10 * ONE_YEAR).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyDHhMmSs);
|
||||||
|
|
||||||
|
// YyDdHhMmSs (10 years, 10 days)
|
||||||
|
c.set_current_value((10 * ONE_YEAR + 10 * ONE_DAY).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyDdHhMmSs);
|
||||||
|
|
||||||
|
// YyDddHhMmSs (10 years, 100 days)
|
||||||
|
c.set_current_value((10 * ONE_YEAR + 100 * ONE_DAY).into());
|
||||||
assert_eq!(c.get_format(), Format::YyDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YyDddHhMmSs);
|
||||||
|
|
||||||
|
// YyyDHhMmSs (100 years)
|
||||||
c.set_current_value((100 * ONE_YEAR).into());
|
c.set_current_value((100 * ONE_YEAR).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyyDHhMmSs);
|
||||||
|
|
||||||
|
// YyyDdHhMmSs (100 years, 10 days)
|
||||||
|
c.set_current_value((100 * ONE_YEAR + 10 * ONE_DAY).into());
|
||||||
|
assert_eq!(c.get_format(), Format::YyyDdHhMmSs);
|
||||||
|
|
||||||
|
// YyyDddHhMmSs (100 years, 100 days)
|
||||||
|
c.set_current_value((100 * ONE_YEAR + 100 * ONE_DAY).into());
|
||||||
assert_eq!(c.get_format(), Format::YyyDddHhMmSs);
|
assert_eq!(c.get_format(), Format::YyyDddHhMmSs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,6 +336,38 @@ fn test_edit_up_stays_in_days() {
|
|||||||
assert!(matches!(c.get_mode(), Mode::Editable(Time::Days, _)));
|
assert!(matches!(c.get_mode(), Mode::Editable(Time::Days, _)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_edit_up_overflow_protection() {
|
||||||
|
let mut c = ClockState::<Timer>::new(ClockStateArgs {
|
||||||
|
initial_value: MAX_DURATION.saturating_sub(ONE_SECOND),
|
||||||
|
current_value: MAX_DURATION.saturating_sub(ONE_SECOND),
|
||||||
|
tick_value: ONE_DECI_SECOND,
|
||||||
|
with_decis: false,
|
||||||
|
app_tx: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
c.toggle_edit();
|
||||||
|
c.edit_next(); // Hours
|
||||||
|
c.edit_next(); // Days
|
||||||
|
c.edit_next(); // Years
|
||||||
|
c.edit_up(); // +1y
|
||||||
|
assert!(Duration::from(*c.get_current_value()) <= MAX_DURATION);
|
||||||
|
c.edit_prev(); // Days
|
||||||
|
c.edit_up(); // +1d
|
||||||
|
assert!(Duration::from(*c.get_current_value()) <= MAX_DURATION);
|
||||||
|
c.edit_prev(); // Hours
|
||||||
|
c.edit_up(); // +1h
|
||||||
|
assert!(Duration::from(*c.get_current_value()) <= MAX_DURATION);
|
||||||
|
c.edit_prev(); // Minutes
|
||||||
|
c.edit_up(); // +1m
|
||||||
|
assert!(Duration::from(*c.get_current_value()) <= MAX_DURATION);
|
||||||
|
c.edit_prev(); // Sec.
|
||||||
|
c.edit_up(); // +1s
|
||||||
|
c.edit_up(); // +1s
|
||||||
|
c.edit_up(); // +1s
|
||||||
|
assert!(Duration::from(*c.get_current_value()) <= MAX_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_down_years_to_days() {
|
fn test_edit_down_years_to_days() {
|
||||||
let mut c = ClockState::<Timer>::new(ClockStateArgs {
|
let mut c = ClockState::<Timer>::new(ClockStateArgs {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user