it counts down
This commit is contained in:
parent
c80ccc9c38
commit
857a064a61
5 changed files with 190 additions and 1 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -588,6 +588,15 @@ dependencies = [
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui_extras"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f698f685bb0ad39e87109e2f695ded0bccde77d5d40bbf7590cb5561c1e3039d"
|
||||||
|
dependencies = [
|
||||||
|
"egui",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "egui_glow"
|
name = "egui_glow"
|
||||||
version = "0.19.0"
|
version = "0.19.0"
|
||||||
|
@ -1011,6 +1020,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"eframe",
|
"eframe",
|
||||||
"egui",
|
"egui",
|
||||||
|
"egui_extras",
|
||||||
"naga 0.10.0",
|
"naga 0.10.0",
|
||||||
"wgpu 0.14.0",
|
"wgpu 0.14.0",
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
name = "katabastird"
|
name = "katabastird"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
rust-version = "1.61"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -9,5 +10,6 @@ edition = "2021"
|
||||||
clap = { version = "4.0.14", features = ["derive", "env", "unicode", "suggestions", "usage"] }
|
clap = { version = "4.0.14", features = ["derive", "env", "unicode", "suggestions", "usage"] }
|
||||||
eframe = { version = "0.19.0", features = ["wgpu"] }
|
eframe = { version = "0.19.0", features = ["wgpu"] }
|
||||||
egui = { version = "0.19.0", features = ["bytemuck"] }
|
egui = { version = "0.19.0", features = ["bytemuck"] }
|
||||||
|
egui_extras = "0.19.0"
|
||||||
naga = { version = "0.10.0", features = ["spv-out", "wgsl-out", "wgsl-in"] }
|
naga = { version = "0.10.0", features = ["spv-out", "wgsl-out", "wgsl-in"] }
|
||||||
wgpu = { version = "0.14.0", features = ["naga", "spirv"] }
|
wgpu = { version = "0.14.0", features = ["naga", "spirv"] }
|
||||||
|
|
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod timer;
|
13
src/main.rs
13
src/main.rs
|
@ -1,3 +1,14 @@
|
||||||
|
use katabastird::timer::Timer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let options = eframe::NativeOptions {
|
||||||
|
renderer: eframe::Renderer::Wgpu,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
eframe::run_native(
|
||||||
|
"eframe template",
|
||||||
|
options,
|
||||||
|
Box::new(|_cc| Box::new(Timer::default())),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
165
src/timer.rs
Normal file
165
src/timer.rs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
use egui::{Color32, Direction, FontId, Layout, RichText, Ui};
|
||||||
|
use egui_extras::{Size, StripBuilder};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use eframe::App;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum CountDirection {
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Timer {
|
||||||
|
direction: CountDirection,
|
||||||
|
duration: Duration,
|
||||||
|
state: State,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum State {
|
||||||
|
Unstarted,
|
||||||
|
Paused(Duration), // time remaining
|
||||||
|
Running(RunningState), // time remaining
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for State {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(Self::Paused(_), Self::Paused(_)) => true,
|
||||||
|
(Self::Running(_), Self::Running(_)) => true,
|
||||||
|
(Self::Unstarted, Self::Unstarted) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for State {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct RunningState {
|
||||||
|
started: Instant,
|
||||||
|
remaining: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Timer {
|
||||||
|
fn default() -> Self {
|
||||||
|
let dur = Duration::from_secs(30);
|
||||||
|
Self {
|
||||||
|
direction: CountDirection::Down,
|
||||||
|
duration: dur,
|
||||||
|
//state: State::Running(dur),
|
||||||
|
state: State::Unstarted,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App for Timer {
|
||||||
|
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||||
|
ctx.request_repaint_after(Duration::from_secs(1));
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
let size = ctx.used_size();
|
||||||
|
let vsize = if size[1].is_normal() {
|
||||||
|
size[1].abs()
|
||||||
|
} else {
|
||||||
|
200.0
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.state {
|
||||||
|
State::Running(_) => self.running(ui, vsize),
|
||||||
|
State::Paused(_) => {}
|
||||||
|
State::Unstarted => {
|
||||||
|
self.unstarted(ui, vsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Timer {
|
||||||
|
fn unstarted(&mut self, ui: &mut Ui, size: f32) {
|
||||||
|
let start = RichText::new("START")
|
||||||
|
.font(FontId::monospace(size * 0.9))
|
||||||
|
.color(Color32::WHITE)
|
||||||
|
.background_color(Color32::LIGHT_GREEN);
|
||||||
|
|
||||||
|
StripBuilder::new(ui)
|
||||||
|
.size(Size::remainder())
|
||||||
|
.cell_layout(Layout::centered_and_justified(egui::Direction::TopDown))
|
||||||
|
.horizontal(|mut strip| {
|
||||||
|
strip.cell(|ui| {
|
||||||
|
if ui.button(start).clicked() {
|
||||||
|
let dur = self.duration;
|
||||||
|
self.state = State::Running(RunningState {
|
||||||
|
started: Instant::now(),
|
||||||
|
remaining: dur,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paused(&mut self, ui: &mut Ui, size: f32) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn running(&mut self, ui: &mut Ui, size: f32) {
|
||||||
|
let tsize = size * 0.2;
|
||||||
|
let text = RichText::new("PAUSE")
|
||||||
|
.font(FontId::monospace(tsize))
|
||||||
|
.color(Color32::GOLD);
|
||||||
|
|
||||||
|
let elapsed;
|
||||||
|
let started;
|
||||||
|
if let State::Running(rs) = self.state {
|
||||||
|
elapsed = Instant::now() - rs.started;
|
||||||
|
started = rs.started;
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
let remaining = self.duration.saturating_sub(elapsed);
|
||||||
|
|
||||||
|
// StripBuilder::vertical();
|
||||||
|
StripBuilder::new(ui)
|
||||||
|
.size(Size::remainder())
|
||||||
|
.cell_layout(Layout::centered_and_justified(Direction::LeftToRight))
|
||||||
|
.horizontal(|mut strip| {
|
||||||
|
strip.cell(|ui| {
|
||||||
|
if ui.button(text).clicked() {
|
||||||
|
self.state = State::Paused(remaining);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if let State::Paused(_) = self.state {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue