diff --git a/cyberpunk-splash/src/main.rs b/cyberpunk-splash/src/main.rs index 019df6a..fe95cd3 100644 --- a/cyberpunk-splash/src/main.rs +++ b/cyberpunk-splash/src/main.rs @@ -3,14 +3,18 @@ use cairo::{ }; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; -use std::{cell::RefCell, rc::Rc}; +use std::{ + cell::RefCell, + rc::Rc, + time::{Duration, Instant}, +}; const WIDTH: i32 = 1920; const HEIGHT: i32 = 1280; pub struct SplashPrivate { text: Rc>, - time: Rc>, + time: Rc>, background: Rc>, } @@ -19,7 +23,7 @@ impl SplashPrivate { *self.text.borrow_mut() = text; } - fn set_time(&self, time: String) { + fn set_time(&self, time: Duration) { *self.time.borrow_mut() = time; } @@ -108,25 +112,6 @@ impl SplashPrivate { let _ = context.stroke(); } - { - context.set_font_size(128.); - let time_extents = context.text_extents(&self.time.borrow()).unwrap(); - let time_baseline_x = center_x - time_extents.width() / 2.; - let time_baseline_y = center_y + 100.; - - let gradient = LinearGradient::new( - time_baseline_x, - time_baseline_y - time_extents.height(), - time_baseline_x, - time_baseline_y, - ); - gradient.add_color_stop_rgb(0.2, 0.2, 0.0, 1.0); - gradient.add_color_stop_rgb(0.8, 0.7, 0.0, 1.0); - context.move_to(time_baseline_x, time_baseline_y); - let _ = context.set_source(gradient); - let _ = context.show_text(&self.time.borrow()); - } - let background = context.pop_group().unwrap(); *self.background.borrow_mut() = background; @@ -150,7 +135,7 @@ impl ObjectSubclass for SplashPrivate { SplashPrivate { text: Rc::new(RefCell::new(String::from(""))), - time: Rc::new(RefCell::new(String::from(""))), + time: Rc::new(RefCell::new(Duration::ZERO)), background: Rc::new(RefCell::new(background)), } } @@ -164,7 +149,7 @@ glib::wrapper! { } impl Splash { - pub fn new(text: String, time: String) -> Self { + pub fn new(text: String, time: Duration) -> Self { let s: Self = Object::builder().build(); s.set_width_request(WIDTH); s.set_height_request(HEIGHT); @@ -175,15 +160,53 @@ impl Splash { s.set_draw_func({ let s = s.clone(); - move |_, context, _width, _height| { + move |_, context, width, height| { let background = s.imp().background.borrow(); let _ = context.set_source(&*background); let _ = context.paint(); + + { + let center_x = width as f64 / 2.; + let center_y = height as f64 / 2.; + + context.select_font_face( + "Alegreya Sans SC", + FontSlant::Normal, + FontWeight::Bold, + ); + context.set_font_size(128.); + + let time = s.imp().time.borrow().clone(); + let minutes = time.as_secs() / 60; + let seconds = time.as_secs() % 60; + let time = format!("{:02}' {:02}\"", minutes, seconds); + + let time_extents = context.text_extents(&time).unwrap(); + let time_baseline_x = center_x - time_extents.width() / 2.; + let time_baseline_y = center_y + 100.; + + let gradient = LinearGradient::new( + time_baseline_x, + time_baseline_y - time_extents.height(), + time_baseline_x, + time_baseline_y, + ); + gradient.add_color_stop_rgb(0.2, 0.2, 0.0, 1.0); + gradient.add_color_stop_rgb(0.8, 0.7, 0.0, 1.0); + context.move_to(time_baseline_x, time_baseline_y); + let _ = context.set_source(gradient); + let _ = context.show_text(&time); + } } }); s } + + pub fn set_time(&self, time: Duration) { + self.imp().set_time(time); + self.queue_draw(); + } } struct AsymLineCutout { @@ -291,10 +314,31 @@ fn main() { .build(); app.connect_activate(move |app| { + let (gtk_tx, gtk_rx) = + gtk::glib::MainContext::channel::(gtk::glib::PRIORITY_DEFAULT); let window = gtk::ApplicationWindow::new(app); window.present(); - window.set_child(Some(&Splash::new("GTK Kifu".to_owned(), "4:23".to_owned()))); + let mut countdown = Duration::from_secs(5 * 60); + let mut next_tick = Instant::now() + Duration::from_secs(1); + + let splash = Splash::new("GTK Kifu".to_owned(), countdown.clone()); + + window.set_child(Some(&splash)); + + gtk_rx.attach(None, move |time| { + splash.set_time(time); + Continue(true) + }); + + std::thread::spawn(move || loop { + std::thread::sleep(Duration::from_secs(1)); + if Instant::now() >= next_tick { + countdown = countdown - Duration::from_secs(1); + let _ = gtk_tx.send(countdown); + next_tick = next_tick + Duration::from_secs(1); + } + }); }); app.run();