Propagate digit size through clock.

This commit is contained in:
shy 2021-04-12 10:21:30 +02:00
parent a95c00aa57
commit f3b48aa7a8
6 changed files with 54 additions and 26 deletions

View file

@ -280,8 +280,8 @@ impl AlarmRoster {
// Reset every alarm. // Reset every alarm.
pub fn reset_all(&mut self) { pub fn reset_all(&mut self) {
for a in &mut self.list { for alarm in &mut self.list {
a.reset(); alarm.reset();
} }
} }
} }

View file

@ -15,7 +15,7 @@ pub struct Clock {
pub paused: bool, pub paused: bool,
paused_at: Option<time::Instant>, paused_at: Option<time::Instant>,
pub color_index: Option<usize>, pub color_index: Option<usize>,
font: font::Font, pub font: font::Font,
} }
impl Clock { impl Clock {
@ -71,6 +71,16 @@ impl Clock {
} }
} }
pub fn get_width(&self) -> u16 {
if self.elapsed >= 3600 {
// Hours
self.font.width * 6 + 3 + 10
} else {
// Minutes and seconds only.
self.font.width * 4 + 2 + 5
}
}
pub fn next_day(&mut self) { pub fn next_day(&mut self) {
// Shift start 24h into the future. // Shift start 24h into the future.
let next = self.start.clone() + time::Duration::from_secs(60 * 60 * 24); let next = self.start.clone() + time::Duration::from_secs(60 * 60 * 24);

View file

@ -1,6 +1,5 @@
pub const DIGIT_HEIGHT: u16 = 5; const DIGIT_HEIGHT: u16 = 5;
pub const DIGIT_WIDTH: u16 = 5;
pub struct Font { pub struct Font {
pub height: u16, pub height: u16,

View file

@ -1,12 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use crate::Config; use crate::Config;
use crate::clock::font::*; use crate::clock::Clock;
// If screen size falls below these values we skip computation of new
// positions.
const MIN_WIDTH: u16 = DIGIT_WIDTH * 6 + 13;
const MIN_HEIGHT: u16 = DIGIT_HEIGHT + 2;
pub struct Position { pub struct Position {
pub line: u16, pub line: u16,
@ -19,6 +14,9 @@ pub struct Layout {
pub plain: bool, // Plain style clock. pub plain: bool, // Plain style clock.
pub width: u16, pub width: u16,
pub height: u16, pub height: u16,
clock_width: u16,
clock_height: u16,
digit_width: u16,
pub clock_sec: Position, pub clock_sec: Position,
pub clock_colon0: Position, pub clock_colon0: Position,
pub clock_min: Position, pub clock_min: Position,
@ -40,6 +38,9 @@ impl Layout {
plain: config.plain, plain: config.plain,
width: 0, width: 0,
height: 0, height: 0,
clock_width: 0,
clock_height: 0,
digit_width: 0,
clock_sec: Position {col: 0, line: 0}, clock_sec: Position {col: 0, line: 0},
clock_colon0: Position {col: 0, line: 0}, clock_colon0: Position {col: 0, line: 0},
clock_min: Position {col: 0, line: 0}, clock_min: Position {col: 0, line: 0},
@ -53,13 +54,16 @@ impl Layout {
} }
} }
pub fn update(&mut self, display_hours: bool, force: bool) { pub fn update(&mut self, clock: &Clock, force: bool) {
if self.force_recalc.swap(false, Ordering::Relaxed) || force { if self.force_recalc.swap(false, Ordering::Relaxed) || force {
let (width, height) = termion::terminal_size() let (width, height) = termion::terminal_size()
.expect("Could not read terminal size!"); .expect("Could not read terminal size!");
self.width = width; self.width = width;
self.height = height; self.height = height;
self.compute(display_hours); self.clock_width = clock.get_width();
self.clock_height = clock.font.height;
self.digit_width = clock.font.width;
self.compute(clock.elapsed >= 3600);
self.force_redraw = true; self.force_redraw = true;
} }
} }
@ -67,15 +71,18 @@ impl Layout {
#[cfg(test)] #[cfg(test)]
pub fn test_update( pub fn test_update(
&mut self, &mut self,
hours: bool, clock: &Clock,
width: u16, width: u16,
height: u16, height: u16,
roster_width: u16, roster_width: u16,
) { ) {
self.width = width; self.width = width;
self.height = height; self.height = height;
self.clock_width = clock.get_width();
self.clock_height = clock.font.height;
self.digit_width = clock.font.width;
self.roster_width = roster_width; self.roster_width = roster_width;
self.compute(hours); self.compute(false);
} }
pub fn can_hold(&self, other: &str) -> bool { pub fn can_hold(&self, other: &str) -> bool {
@ -87,27 +94,27 @@ impl Layout {
// terminal. // terminal.
fn compute(&mut self, display_hours: bool) { fn compute(&mut self, display_hours: bool) {
// Prevent integer overflow at very low screen sizes. // Prevent integer overflow at very low screen sizes.
if self.width < MIN_WIDTH || self.height < MIN_HEIGHT { return; } if self.width < self.clock_width || self.height < self.clock_height { return; }
let middle: u16 = self.height / 2 - 1; let middle: u16 = self.height / 2 - 1;
if display_hours { if display_hours {
// Seconds digits. // Seconds digits.
self.clock_sec.col = (self.width + self.roster_width) / 2 + DIGIT_WIDTH + 6; self.clock_sec.col = (self.width + self.roster_width) / 2 + self.digit_width + 6;
// Colon separating minutes from seconds. // Colon separating minutes from seconds.
self.clock_colon0.col = (self.width + self.roster_width) / 2 + DIGIT_WIDTH + 3; self.clock_colon0.col = (self.width + self.roster_width) / 2 + self.digit_width + 3;
// Minute digits. // Minute digits.
self.clock_min.col = (self.width + self.roster_width) / 2 - DIGIT_WIDTH; self.clock_min.col = (self.width + self.roster_width) / 2 - self.digit_width;
// Colon separating hours from minutes. // Colon separating hours from minutes.
self.clock_colon1 = Position { self.clock_colon1 = Position {
col: (self.width + self.roster_width) / 2 - (DIGIT_WIDTH + 3), col: (self.width + self.roster_width) / 2 - (self.digit_width + 3),
line: middle, line: middle,
}; };
// Hour digits. // Hour digits.
self.clock_hr = Position { self.clock_hr = Position {
col: (self.width + self.roster_width) / 2 - (DIGIT_WIDTH * 3 + 6), col: (self.width + self.roster_width) / 2 - (self.digit_width * 3 + 6),
line: middle, line: middle,
}; };
} else { } else {
@ -116,7 +123,7 @@ impl Layout {
// Colon separating minutes from seconds. // Colon separating minutes from seconds.
self.clock_colon0.col = (self.width + self.roster_width) / 2; self.clock_colon0.col = (self.width + self.roster_width) / 2;
// Minute digits. // Minute digits.
self.clock_min.col = (self.width + self.roster_width) / 2 - (DIGIT_WIDTH * 2 + 3); self.clock_min.col = (self.width + self.roster_width) / 2 - (self.digit_width * 2 + 3);
} }
self.clock_sec.line = middle; self.clock_sec.line = middle;
@ -125,7 +132,7 @@ impl Layout {
// Days (based on position of seconds). // Days (based on position of seconds).
self.clock_days = Position { self.clock_days = Position {
line: self.clock_sec.line + DIGIT_HEIGHT, line: self.clock_sec.line + self.digit_width,
col: self.clock_sec.col, col: self.clock_sec.col,
}; };

View file

@ -130,7 +130,7 @@ pub fn run(
// Update window size information and calculate the clock position. // Update window size information and calculate the clock position.
// Also enforce recalculation of layout if we start displaying // Also enforce recalculation of layout if we start displaying
// hours. // hours.
layout.update(clock.elapsed >= 3600, clock.elapsed == 3600); layout.update(&clock, clock.elapsed == 3600);
// Check for exceeded alarms. // Check for exceeded alarms.
if let Some((time, label)) = alarm_roster.check(&mut clock, &layout, &mut countdown) { if let Some((time, label)) = alarm_roster.check(&mut clock, &layout, &mut countdown) {

View file

@ -1,4 +1,5 @@
use crate::layout::Layout; use crate::layout::Layout;
use crate::clock::Clock;
use crate::Config; use crate::Config;
fn default_config() -> Config { fn default_config() -> Config {
@ -13,12 +14,23 @@ fn default_config() -> Config {
#[test] #[test]
fn layout_computation() { fn layout_computation() {
let config = default_config(); let config = default_config();
let mut clock = Clock::new(&config);
let mut layout = Layout::new(&config); let mut layout = Layout::new(&config);
// Two segment display.
for roster_width in &[0, 10, 20, 30, 40] { for roster_width in &[0, 10, 20, 30, 40] {
for width in 0..256 { for width in 0..256 {
for height in 0..128 { for height in 0..128 {
layout.test_update(height & 1 == 0, width, height, *roster_width); layout.test_update(&clock, width, height, *roster_width);
}
}
}
// Three segment display.
clock.elapsed = 3600;
for roster_width in &[0, 10, 20, 30, 40] {
for width in 0..256 {
for height in 0..128 {
layout.test_update(&clock, width, height, *roster_width);
} }
} }
} }