diff --git a/cyberpunk-splash/src/main.rs b/cyberpunk-splash/src/main.rs index fe95cd3..70776ca 100644 --- a/cyberpunk-splash/src/main.rs +++ b/cyberpunk-splash/src/main.rs @@ -1,5 +1,6 @@ use cairo::{ Context, FontSlant, FontWeight, Format, ImageSurface, LineCap, LinearGradient, Pattern, + TextExtents, }; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; @@ -16,6 +17,7 @@ pub struct SplashPrivate { text: Rc>, time: Rc>, background: Rc>, + time_extents: Rc>>, } impl SplashPrivate { @@ -137,6 +139,7 @@ impl ObjectSubclass for SplashPrivate { text: Rc::new(RefCell::new(String::from(""))), time: Rc::new(RefCell::new(Duration::ZERO)), background: Rc::new(RefCell::new(background)), + time_extents: Rc::new(RefCell::new(None)), } } } @@ -165,10 +168,14 @@ impl Splash { let _ = context.set_source(&*background); let _ = context.paint(); - { - let center_x = width as f64 / 2.; - let center_y = height as f64 / 2.; + let time = s.imp().time.borrow().clone(); + let minutes = time.as_secs() / 60; + let seconds = time.as_secs() % 60; + let center_x = width as f64 / 2.; + let center_y = height as f64 / 2.; + + { context.select_font_face( "Alegreya Sans SC", FontSlant::Normal, @@ -176,12 +183,15 @@ impl Splash { ); 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 mut saved_extents = s.imp().time_extents.borrow_mut(); + if saved_extents.is_none() { + *saved_extents = Some(time_extents.clone()); + } + let time_baseline_x = center_x - time_extents.width() / 2.; let time_baseline_y = center_y + 100.; @@ -196,6 +206,23 @@ impl Splash { context.move_to(time_baseline_x, time_baseline_y); let _ = context.set_source(gradient); let _ = context.show_text(&time); + }; + + match *s.imp().time_extents.borrow() { + Some(extents) => { + context.set_source_rgb(0.7, 0.0, 1.0); + let time_meter = SlashMeter { + orientation: gtk::Orientation::Horizontal, + start_x: center_x + extents.width() / 2. + 50., + start_y: center_y + 100., + count: 5, + fill_count: minutes as u8, + height: 60., + length: 100., + }; + time_meter.draw(&context); + } + None => {} } } }); @@ -308,6 +335,46 @@ impl AsymLine { } } +struct SlashMeter { + orientation: gtk::Orientation, + start_x: f64, + start_y: f64, + count: u8, + fill_count: u8, + height: f64, + length: f64, +} + +impl SlashMeter { + fn draw(&self, context: &Context) { + match self.orientation { + gtk::Orientation::Horizontal => { + let angle: f64 = 0.8; + let run = self.height / angle.tan(); + let width = self.length as f64 / (self.count as f64 * 2.); + + for c in 0..self.count { + context.set_line_width(1.); + + let start_x = self.start_x + c as f64 * width * 2.; + context.move_to(start_x, self.start_y); + context.line_to(start_x + run, self.start_y - self.height); + context.line_to(start_x + run + width, self.start_y - self.height); + context.line_to(start_x + width, self.start_y); + context.line_to(start_x, self.start_y); + if c < self.fill_count { + let _ = context.fill(); + } else { + let _ = context.stroke(); + } + } + } + gtk::Orientation::Vertical => {} + _ => panic!("unknown orientation"), + } + } +} + fn main() { let app = gtk::Application::builder() .application_id("com.luminescent-dreams.cyberpunk-splash")