use std::{fs::File, io::Read, path::Path, rc::Rc, time::Duration}; use cyberpunk::{AsymLine, GlowPen, Pen, Text}; use glib::Object; use gtk::{glib, prelude::*, subclass::prelude::*}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "lowercase")] enum TextArea { Top, Middle, Bottom, } #[derive(Serialize, Deserialize, Debug)] struct Fade { duration: Duration, } #[derive(Serialize, Deserialize, Debug)] enum AnimationIn { Fade(Fade), } #[derive(Serialize, Deserialize, Debug)] enum AnimationOut { Fade(Fade), } #[derive(Serialize, Deserialize, Debug)] struct ScriptElement { text: String, position: TextArea, transition_in: AnimationIn, } #[derive(Serialize, Deserialize, Debug)] struct Script(Vec); impl Script { fn from_file(path: &Path) -> Result { let mut buf: Vec = Vec::new(); let mut f = File::open(path).unwrap(); f.read_to_end(&mut buf).unwrap(); let script = serde_yml::from_slice(&buf)?; Ok(Self(script)) } fn iter<'a>(&'a self) -> impl Iterator { self.0.iter() } } #[derive(Default)] pub struct CyberScreenPrivate {} #[glib::object_subclass] impl ObjectSubclass for CyberScreenPrivate { const NAME: &'static str = "CyberScreen"; type Type = CyberScreen; type ParentType = gtk::DrawingArea; } impl ObjectImpl for CyberScreenPrivate {} impl WidgetImpl for CyberScreenPrivate {} impl DrawingAreaImpl for CyberScreenPrivate {} glib::wrapper! { pub struct CyberScreen(ObjectSubclass) @extends gtk::DrawingArea, gtk::Widget; } impl CyberScreen { pub fn new() -> Self { let s: Self = Object::builder().build(); s.set_draw_func({ move |_, context, width, height| { let _ = context.set_source_rgb(0., 0., 0.); let _ = context.paint(); let pen = GlowPen::new(width, height, 2., 8., (0.7, 0., 1.)); AsymLine { orientation: gtk::Orientation::Horizontal, start_x: 50., start_y: height as f64 / 2., start_length: 75., height: 50., total_length: 200., invert: false, } .draw(&pen); pen.stroke(); let tracery = pen.finish(); let _ = context.set_source(tracery); let _ = context.paint(); Text::new("Test text".to_owned(), (0.7, 0., 1.)).draw(&context); } }); s } } fn main() { /* let script: Script = Script(vec![ScriptElement { text: "abcdefg".to_owned(), position: TextArea::Top, transition_in: AnimationIn::Fade(Fade { duration: Duration::from_secs(10), }), }]); println!("{}", serde_yml::to_string(&script).unwrap()); */ let script = Script::from_file(Path::new("./script.yml")).unwrap(); for element in script.iter() { println!("{:?}", element); } let app = gtk::Application::builder() .application_id("com.luminescent-dreams.cyberpunk-slideshow") .build(); app.connect_activate(|app| { let window = gtk::ApplicationWindow::new(app); window.present(); let screen = CyberScreen::new(); window.set_child(Some(&screen)); window.set_width_request(800); window.set_height_request(600); window.present(); }); app.run(); }