Add dynamic font scaling, hotkeys for quitting.

Huge thanks to `@AlexChaplinBraz` in the egui discord for help with the fonts!
This commit is contained in:
Joe Ardent 2022-10-17 13:53:46 -07:00
parent b6b3be19ec
commit ad7b0c9d4d
2 changed files with 52 additions and 30 deletions

View file

@ -7,7 +7,11 @@ use egui_extras::{Size, StripBuilder};
use crate::{cli::Cli, util::*}; use crate::{cli::Cli, util::*};
const MIN_REPAINT: Duration = Duration::from_millis(100); const MIN_REPAINT: Duration = Duration::from_millis(183); // one frame before 200ms
const MAX_REPAINT: Duration = Duration::from_millis(500);
const DIGIT_FACTOR: f32 = 0.4;
const TEXT_FACTOR: f32 = 0.2;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum CountDirection { pub enum CountDirection {
@ -20,15 +24,16 @@ pub struct Timer {
direction: CountDirection, direction: CountDirection,
duration: Duration, duration: Duration,
state: TimerState, state: TimerState,
tstart: Instant, tstart: Instant, // so we can blink
alarm: Option<String>, alarm: Option<String>,
height: Option<f32>,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum TimerState { enum TimerState {
Unstarted, Unstarted,
Paused(ChronoState), // time remaining Paused(ChronoState),
Running(ChronoState), // time remaining Running(ChronoState),
Finished, Finished,
} }
@ -53,15 +58,10 @@ struct ChronoState {
} }
impl App for Timer { impl App for Timer {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
ctx.request_repaint_after(Duration::from_secs(1)); ctx.request_repaint_after(MAX_REPAINT);
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
let size = ctx.used_size(); let vsize = self.height.unwrap_or(500.0);
let vsize = if size.x.is_normal() {
size.x.abs()
} else {
400.0
};
match self.state { match self.state {
TimerState::Unstarted => self.unstarted(ui, vsize), TimerState::Unstarted => self.unstarted(ui, vsize),
@ -75,6 +75,10 @@ impl App for Timer {
TimerState::Finished => self.finished(ui, vsize), TimerState::Finished => self.finished(ui, vsize),
} }
// check for quit key
if ui.input().key_pressed(egui::Key::Q) || ui.input().key_pressed(egui::Key::Escape) {
frame.close();
}
}); });
} }
} }
@ -112,6 +116,7 @@ impl Timer {
state: TimerState::Unstarted, state: TimerState::Unstarted,
tstart: Instant::now(), tstart: Instant::now(),
alarm: cli.alarm, alarm: cli.alarm,
height: None,
}; };
if cli.running { if cli.running {
let cs = ChronoState { let cs = ChronoState {
@ -125,12 +130,14 @@ impl Timer {
} }
fn unstarted(&mut self, ui: &mut Ui, size: f32) { fn unstarted(&mut self, ui: &mut Ui, size: f32) {
let tsize = size * 0.5;
let start = RichText::new("START") let start = RichText::new("START")
.font(FontId::monospace(size * 0.9)) .font(FontId::monospace(tsize))
.size(tsize)
.color(Color32::WHITE) .color(Color32::WHITE)
.background_color(Color32::LIGHT_GREEN); .background_color(Color32::LIGHT_GREEN);
StripBuilder::new(ui) let height = StripBuilder::new(ui)
.size(Size::remainder()) .size(Size::remainder())
.cell_layout(Layout::centered_and_justified(egui::Direction::TopDown)) .cell_layout(Layout::centered_and_justified(egui::Direction::TopDown))
.horizontal(|mut strip| { .horizontal(|mut strip| {
@ -143,13 +150,17 @@ impl Timer {
}); });
} }
}); });
}); })
.rect
.height();
self.height = Some(height);
} }
fn running(&mut self, ui: &mut Ui, size: f32) { fn running(&mut self, ui: &mut Ui, size: f32) {
let tsize = size * 0.3; let tsize = size * TEXT_FACTOR;
let text = RichText::new("PAUSE") let text = RichText::new("PAUSE")
.font(FontId::monospace(tsize)) .font(FontId::monospace(tsize))
.size(tsize)
.color(Color32::GOLD); .color(Color32::GOLD);
let elapsed; let elapsed;
@ -164,7 +175,7 @@ impl Timer {
let remaining = remaining.saturating_sub(elapsed); let remaining = remaining.saturating_sub(elapsed);
StripBuilder::new(ui) let height = StripBuilder::new(ui)
.size(Size::relative(0.3333)) .size(Size::relative(0.3333))
.size(Size::remainder()) .size(Size::remainder())
.cell_layout(Layout::centered_and_justified(Direction::LeftToRight)) .cell_layout(Layout::centered_and_justified(Direction::LeftToRight))
@ -183,10 +194,14 @@ impl Timer {
}; };
// now the numbers // now the numbers
let color = Color32::DARK_GRAY; let color = Color32::DARK_GRAY;
let tsize = size * 0.7; let tsize = size * DIGIT_FACTOR;
display_digits(&mut strip, remaining, color, tsize); display_digits(&mut strip, remaining, color, tsize);
}); })
.rect
.height();
self.height = Some(height);
if remaining.is_zero() { if remaining.is_zero() {
if let Some(alarm_file) = &self.alarm { if let Some(alarm_file) = &self.alarm {
@ -215,7 +230,7 @@ impl Timer {
fn paused(&mut self, ui: &mut Ui, vsize: f32) { fn paused(&mut self, ui: &mut Ui, vsize: f32) {
let elapsed; let elapsed;
let mut is_running = false; let mut is_running = false;
let tsize = vsize * 0.3; let tsize = vsize * TEXT_FACTOR;
if let TimerState::Paused(cs) = self.state { if let TimerState::Paused(cs) = self.state {
elapsed = cs.remaining; elapsed = cs.remaining;
} else { } else {
@ -223,7 +238,7 @@ impl Timer {
} }
let remaining = elapsed; let remaining = elapsed;
StripBuilder::new(ui) let height = StripBuilder::new(ui)
.size(Size::relative(0.33333)) .size(Size::relative(0.33333))
.size(Size::remainder()) .size(Size::remainder())
.cell_layout(Layout::centered_and_justified(Direction::LeftToRight)) .cell_layout(Layout::centered_and_justified(Direction::LeftToRight))
@ -236,7 +251,8 @@ impl Timer {
pstrip.cell(|ui| { pstrip.cell(|ui| {
let resume = RichText::new("RESUME") let resume = RichText::new("RESUME")
.color(Color32::GREEN) .color(Color32::GREEN)
.font(FontId::monospace(tsize)); .font(FontId::monospace(tsize))
.size(tsize);
if ui.button(resume).clicked() { if ui.button(resume).clicked() {
is_running = true; is_running = true;
} }
@ -244,7 +260,8 @@ impl Timer {
pstrip.cell(|ui| { pstrip.cell(|ui| {
let reset = RichText::new("RESET") let reset = RichText::new("RESET")
.color(Color32::RED) .color(Color32::RED)
.font(FontId::monospace(tsize)); .font(FontId::monospace(tsize))
.size(tsize);
if ui.button(reset).clicked() { if ui.button(reset).clicked() {
self.state = TimerState::Unstarted; self.state = TimerState::Unstarted;
} }
@ -264,8 +281,11 @@ impl Timer {
CountDirection::Down => remaining, CountDirection::Down => remaining,
CountDirection::Up => self.duration - remaining, CountDirection::Up => self.duration - remaining,
}; };
display_digits(&mut strip, remaining, color, vsize * 0.7); display_digits(&mut strip, remaining, color, vsize * DIGIT_FACTOR);
}); })
.rect
.height();
self.height = Some(height);
if is_running { if is_running {
let cs = ChronoState { let cs = ChronoState {
@ -292,9 +312,11 @@ impl Timer {
.cell_layout(Layout::centered_and_justified(Direction::TopDown)) .cell_layout(Layout::centered_and_justified(Direction::TopDown))
.horizontal(|mut pstrip| { .horizontal(|mut pstrip| {
pstrip.cell(|ui| { pstrip.cell(|ui| {
let reset = RichText::new("RESET") let tsize = vsize * 0.3;
.color(Color32::GOLD) let reset = RichText::new("RESTART")
.font(FontId::monospace(vsize * 0.3)); .color(Color32::DARK_GREEN)
.font(FontId::monospace(tsize))
.size(tsize);
if ui.button(reset).clicked() { if ui.button(reset).clicked() {
self.state = TimerState::Unstarted; self.state = TimerState::Unstarted;
} }
@ -309,7 +331,7 @@ impl Timer {
Color32::DARK_GRAY Color32::DARK_GRAY
} }
}; };
display_digits(&mut strip, remaining, color, vsize * 0.7); display_digits(&mut strip, remaining, color, vsize * DIGIT_FACTOR);
}); });
} }
} }

View file

@ -3,7 +3,7 @@ use std::time::Duration;
use egui::{Color32, Direction, FontId, Layout, RichText}; use egui::{Color32, Direction, FontId, Layout, RichText};
use egui_extras::{Size, Strip}; use egui_extras::{Size, Strip};
pub fn format_digits(digits: u64, size: f32, color: Color32) -> RichText { fn format_digits(digits: u64, size: f32, color: Color32) -> RichText {
RichText::new(format!("{:02}", digits)) RichText::new(format!("{:02}", digits))
.font(FontId::monospace(size)) .font(FontId::monospace(size))
.color(color) .color(color)