144 lines
3.6 KiB
Rust
144 lines
3.6 KiB
Rust
|
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<ScriptElement>);
|
||
|
|
||
|
impl Script {
|
||
|
fn from_file(path: &Path) -> Result<Script, serde_yml::Error> {
|
||
|
let mut buf: Vec<u8> = 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<Item = &'a ScriptElement> {
|
||
|
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<CyberScreenPrivate>) @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();
|
||
|
}
|