This commit is contained in:
Joe Ardent 2022-10-13 17:11:50 -07:00
parent 857a064a61
commit b49625a973
2 changed files with 117 additions and 52 deletions

View file

@ -1,13 +1,15 @@
use egui::Vec2;
use katabastird::timer::Timer; use katabastird::timer::Timer;
fn main() { fn main() {
let options = eframe::NativeOptions { let options = eframe::NativeOptions {
renderer: eframe::Renderer::Wgpu, renderer: eframe::Renderer::Wgpu,
initial_window_size: Some(Vec2::new(1400.0, 800.0)),
..Default::default() ..Default::default()
}; };
eframe::run_native( eframe::run_native(
"eframe template", "katabastird",
options, options,
Box::new(|_cc| Box::new(Timer::default())), Box::new(|_cc| Box::new(Timer::default())),
); );

View file

@ -20,8 +20,8 @@ pub struct Timer {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum State { enum State {
Unstarted, Unstarted,
Paused(Duration), // time remaining Paused(ChronoState), // time remaining
Running(RunningState), // time remaining Running(ChronoState), // time remaining
} }
impl PartialEq for State { impl PartialEq for State {
@ -38,7 +38,7 @@ impl PartialEq for State {
impl Eq for State {} impl Eq for State {}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
struct RunningState { struct ChronoState {
started: Instant, started: Instant,
remaining: Duration, remaining: Duration,
} }
@ -49,35 +49,51 @@ impl Default for Timer {
Self { Self {
direction: CountDirection::Down, direction: CountDirection::Down,
duration: dur, duration: dur,
//state: State::Running(dur),
state: State::Unstarted, state: State::Unstarted,
} }
} }
} }
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(Duration::from_secs(1));
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
let size = ctx.used_size(); let size = ctx.used_size();
let vsize = if size[1].is_normal() { let vsize = if size[1].is_normal() {
size[1].abs() size[1].abs()
} else { } else {
200.0 600.0
}; };
match self.state { match self.state {
State::Running(_) => self.running(ui, vsize), State::Unstarted => self.unstarted(ui, vsize),
State::Paused(_) => {} _ => self.running(ui, vsize),
State::Unstarted => {
self.unstarted(ui, vsize);
}
} }
}); });
} }
} }
impl Timer { impl Timer {
pub fn new(duration: Duration, direction: CountDirection, paused: bool) -> Self {
if paused {
Timer {
duration,
direction,
state: State::Unstarted,
}
} else {
let cs = ChronoState {
remaining: duration,
started: Instant::now(),
};
Timer {
duration,
direction,
state: State::Running(cs),
}
}
}
fn unstarted(&mut self, ui: &mut Ui, size: f32) { fn unstarted(&mut self, ui: &mut Ui, size: f32) {
let start = RichText::new("START") let start = RichText::new("START")
.font(FontId::monospace(size * 0.9)) .font(FontId::monospace(size * 0.9))
@ -91,7 +107,7 @@ impl Timer {
strip.cell(|ui| { strip.cell(|ui| {
if ui.button(start).clicked() { if ui.button(start).clicked() {
let dur = self.duration; let dur = self.duration;
self.state = State::Running(RunningState { self.state = State::Running(ChronoState {
started: Instant::now(), started: Instant::now(),
remaining: dur, remaining: dur,
}); });
@ -100,66 +116,113 @@ impl Timer {
}); });
} }
fn paused(&mut self, ui: &mut Ui, size: f32) {
todo!()
}
fn running(&mut self, ui: &mut Ui, size: f32) { fn running(&mut self, ui: &mut Ui, size: f32) {
let tsize = size * 0.2; let tsize = size * 0.3;
let text = RichText::new("PAUSE") let text = RichText::new("PAUSE")
.font(FontId::monospace(tsize)) .font(FontId::monospace(tsize))
.color(Color32::GOLD); .color(Color32::GOLD);
let elapsed; let elapsed;
let started; let started;
let mut is_paused;
if let State::Running(rs) = self.state { if let State::Running(rs) = self.state {
elapsed = Instant::now() - rs.started; elapsed = Instant::now() - rs.started;
started = rs.started; started = rs.started;
is_paused = false;
} else if let State::Paused(cs) = self.state {
elapsed = cs.remaining;
started = Instant::now() - (self.duration - elapsed);
is_paused = true;
} else { } else {
unreachable!() unreachable!()
} }
let remaining = self.duration.saturating_sub(elapsed); let remaining = if is_paused {
elapsed
} else {
self.duration.saturating_sub(elapsed)
};
// StripBuilder::vertical();
StripBuilder::new(ui) StripBuilder::new(ui)
.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))
.horizontal(|mut strip| { .vertical(|mut strip| {
strip.cell(|ui| { if is_paused {
if ui.button(text).clicked() { strip.strip(|pstrip| {
self.state = State::Paused(remaining); pstrip
} .sizes(Size::remainder(), 2)
.cell_layout(Layout::centered_and_justified(Direction::TopDown))
.horizontal(|mut pstrip| {
pstrip.cell(|ui| {
let resume = RichText::new("RESUME")
.color(Color32::GREEN)
.font(FontId::monospace(tsize));
if ui.button(resume).clicked() {
is_paused = false;
}
});
pstrip.cell(|ui| {
let reset = RichText::new("RESET")
.color(Color32::RED)
.font(FontId::monospace(tsize));
if ui.button(reset).clicked() {
self.state = State::Unstarted;
is_paused = true;
}
});
});
});
} else {
// first the pause
strip.cell(|ui| {
if ui.button(text).clicked() {
is_paused = true;
}
});
}
let remaining = match self.direction {
CountDirection::Down => remaining,
_ => self.duration - remaining,
};
// now the numbers
let hours = remaining.as_secs() / 3600;
let minutes = (remaining.as_secs() / 60) % 60;
let seconds = remaining.as_secs() % 60;
let tsize = size * 0.7;
let hours = RichText::new(format!("{:02}", hours)).font(FontId::monospace(tsize));
let minutes =
RichText::new(format!("{:02}", minutes)).font(FontId::monospace(tsize));
let seconds =
RichText::new(format!("{:02}", seconds)).font(FontId::monospace(tsize));
strip.strip(|strip| {
strip
.sizes(Size::relative(0.33), 3)
.cell_layout(Layout::centered_and_justified(Direction::TopDown))
.horizontal(|mut strip| {
strip.cell(|ui| {
ui.label(hours);
});
strip.cell(|ui| {
ui.label(minutes);
});
strip.cell(|ui| {
ui.label(seconds);
});
});
}); });
}); });
if let State::Paused(_) = self.state { let cs = ChronoState { remaining, started };
return; if is_paused {
if self.state == State::Unstarted {
return;
}
self.state = State::Paused(cs);
} else {
self.state = State::Running(cs);
} }
self.state = State::Running(RunningState { started, remaining });
let hours = remaining.as_secs() / 3600;
let minutes = (remaining.as_secs() / 60) % 60;
let seconds = remaining.as_secs() % 60;
let tsize = size * 0.7;
let hours = RichText::new(format!("{:02}", hours)).font(FontId::monospace(tsize));
let minutes = RichText::new(format!("{:02}", minutes)).font(FontId::monospace(tsize));
let seconds = RichText::new(format!("{:02}", seconds)).font(FontId::monospace(tsize));
StripBuilder::new(ui)
.sizes(Size::relative(0.33), 3)
.cell_layout(Layout::centered_and_justified(Direction::TopDown))
.horizontal(|mut strip| {
strip.cell(|ui| {
ui.label(hours);
});
strip.cell(|ui| {
ui.label(minutes);
});
strip.cell(|ui| {
ui.label(seconds);
});
});
} }
} }