131 lines
4.1 KiB
Rust
131 lines
4.1 KiB
Rust
|
use crate::Config;
|
||
|
use crate::common::*;
|
||
|
|
||
|
// 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 line: u16,
|
||
|
pub col: u16,
|
||
|
}
|
||
|
|
||
|
pub struct Layout {
|
||
|
pub force_redraw: bool, // Redraw elements on screen.
|
||
|
pub force_recalc: bool, // Recalculate position of elements.
|
||
|
pub plain: bool, // Plain style clock.
|
||
|
pub width: u16,
|
||
|
pub height: u16,
|
||
|
pub clock_sec: Position,
|
||
|
pub clock_colon0: Position,
|
||
|
pub clock_min: Position,
|
||
|
pub clock_colon1: Position,
|
||
|
pub clock_hr: Position,
|
||
|
pub clock_days: Position,
|
||
|
pub roster: Position,
|
||
|
pub roster_width: u16,
|
||
|
pub roster_height: u16,
|
||
|
pub buffer: Position,
|
||
|
pub error: Position,
|
||
|
}
|
||
|
|
||
|
impl Layout {
|
||
|
pub fn new(config: &Config) -> Layout {
|
||
|
Layout {
|
||
|
force_redraw: true,
|
||
|
force_recalc: false,
|
||
|
plain: config.plain,
|
||
|
width: 0,
|
||
|
height: 0,
|
||
|
clock_sec: Position {col: 0, line: 0},
|
||
|
clock_colon0: Position {col: 0, line: 0},
|
||
|
clock_min: Position {col: 0, line: 0},
|
||
|
clock_colon1: Position {col: 0, line: 0},
|
||
|
clock_hr: Position {col: 0, line: 0},
|
||
|
clock_days: Position {col: 0, line: 0},
|
||
|
roster: Position {col: 1, line: 3},
|
||
|
roster_width: 0,
|
||
|
roster_height: 0,
|
||
|
buffer: Position {col: 0, line: 0},
|
||
|
error: Position {col: 0, line: 0},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn update(&mut self, display_hours: bool) {
|
||
|
let (width, height) = termion::terminal_size()
|
||
|
.expect("Could not read terminal size!");
|
||
|
|
||
|
if self.force_recalc || self.width != width || self.height != height {
|
||
|
self.width = width;
|
||
|
self.height = height;
|
||
|
self.compute(display_hours);
|
||
|
self.force_redraw = true;
|
||
|
self.force_recalc = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Compute the position of various elements based on the size of the
|
||
|
// terminal.
|
||
|
fn compute(&mut self, display_hours: bool) {
|
||
|
let middle: u16 = self.height / 2 - 1;
|
||
|
|
||
|
// Prevent integer overflow on very low screen sizes.
|
||
|
if self.width < MIN_WIDTH || self.height < MIN_HEIGHT { return; }
|
||
|
|
||
|
if display_hours {
|
||
|
// Seconds digits.
|
||
|
self.clock_sec.col = (self.width + self.roster_width) / 2 + DIGIT_WIDTH + 6;
|
||
|
// Colon separating minutes from seconds.
|
||
|
self.clock_colon0.col = (self.width + self.roster_width) / 2 + DIGIT_WIDTH + 3;
|
||
|
// Minute digits.
|
||
|
self.clock_min.col = (self.width + self.roster_width) / 2 - DIGIT_WIDTH;
|
||
|
|
||
|
// Colon separating hours from minutes.
|
||
|
self.clock_colon1 = Position {
|
||
|
col: (self.width + self.roster_width) / 2 - (DIGIT_WIDTH + 3),
|
||
|
line: middle,
|
||
|
};
|
||
|
|
||
|
// Hour digits.
|
||
|
self.clock_hr = Position {
|
||
|
col: (self.width + self.roster_width) / 2 - (DIGIT_WIDTH * 3 + 6),
|
||
|
line: middle,
|
||
|
};
|
||
|
} else {
|
||
|
// Seconds digits.
|
||
|
self.clock_sec.col = (self.width + self.roster_width) / 2 + 3;
|
||
|
// Colon separating minutes from seconds.
|
||
|
self.clock_colon0.col = (self.width + self.roster_width) / 2;
|
||
|
// Minute digits.
|
||
|
self.clock_min.col = (self.width + self.roster_width) / 2 - (DIGIT_WIDTH * 2 + 3);
|
||
|
}
|
||
|
|
||
|
self.clock_sec.line = middle;
|
||
|
self.clock_colon0.line = middle;
|
||
|
self.clock_min.line = middle;
|
||
|
|
||
|
// Days (based on position of seconds).
|
||
|
self.clock_days = Position {
|
||
|
line: self.clock_sec.line + DIGIT_HEIGHT + 1,
|
||
|
col: self.clock_sec.col,
|
||
|
};
|
||
|
|
||
|
// Alarm roster height.
|
||
|
self.roster_height = self.height - self.roster.line - 1;
|
||
|
|
||
|
// Input buffer.
|
||
|
self.buffer = Position {
|
||
|
line: self.height,
|
||
|
col: 1,
|
||
|
};
|
||
|
|
||
|
// Error messages.
|
||
|
self.error = Position {
|
||
|
line: self.height,
|
||
|
col: 12,
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|