monorepo/cyberpunk-splash/src/main.rs

199 lines
6.2 KiB
Rust
Raw Normal View History

use cairo::{Context, FontFace, Format, ImageSurface, LineCap, Pattern};
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use std::{cell::RefCell, rc::Rc};
const WIDTH: i32 = 800;
const HEIGHT: i32 = 800;
pub struct SplashPrivate {
text: Rc<RefCell<String>>,
time: Rc<RefCell<String>>,
background: Rc<RefCell<Pattern>>,
}
impl SplashPrivate {
fn set_text(&self, text: String) {
*self.text.borrow_mut() = text;
}
fn set_time(&self, time: String) {
*self.time.borrow_mut() = time;
}
fn redraw_background(&self) {
let background = ImageSurface::create(Format::Rgb24, WIDTH, HEIGHT).unwrap();
let context = Context::new(background).unwrap();
context.push_group();
context.set_source_rgb(0., 0., 0.);
let _ = context.paint();
context.set_font_size(64.);
let title_extents = context.text_extents(&self.text.borrow()).unwrap();
context.set_source_rgb(0.7, 0., 1.);
context.set_line_width(5.);
context.set_line_cap(LineCap::Round);
AsymLineReturn {
orientation: gtk::Orientation::Horizontal,
start_x: 20.,
start_y: 20.,
start_length: 200.,
center_length: title_extents.y_advance(),
end_length: 100.,
width: title_extents.height(),
}
.draw(&context);
let _ = context.stroke();
let background = context.pop_group().unwrap();
*self.background.borrow_mut() = background;
}
}
#[glib::object_subclass]
impl ObjectSubclass for SplashPrivate {
const NAME: &'static str = "Splash";
type Type = Splash;
type ParentType = gtk::DrawingArea;
fn new() -> SplashPrivate {
// Set up a default plain black background
let background = ImageSurface::create(Format::Rgb24, WIDTH, HEIGHT).unwrap();
let context = Context::new(background).unwrap();
context.push_group();
context.set_source_rgb(0., 0., 0.);
let _ = context.paint();
let background = context.pop_group().unwrap();
SplashPrivate {
text: Rc::new(RefCell::new(String::from(""))),
time: Rc::new(RefCell::new(String::from(""))),
background: Rc::new(RefCell::new(background)),
}
}
}
impl ObjectImpl for SplashPrivate {}
impl WidgetImpl for SplashPrivate {}
impl DrawingAreaImpl for SplashPrivate {}
glib::wrapper! {
pub struct Splash(ObjectSubclass<SplashPrivate>) @extends gtk::DrawingArea, gtk::Widget;
}
impl Splash {
pub fn new(text: String, time: String) -> Self {
let s: Self = Object::builder().build();
s.set_width_request(WIDTH);
s.set_height_request(HEIGHT);
s.imp().set_text(text);
s.imp().set_time(time);
s.imp().redraw_background();
s.set_draw_func({
let s = s.clone();
move |_, context, _width, _height| {
let background = s.imp().background.borrow();
let _ = context.set_source(&*background);
let _ = context.paint();
}
});
s
}
}
struct AsymLineReturn {
orientation: gtk::Orientation,
start_x: f64,
start_y: f64,
start_length: f64,
center_length: f64,
end_length: f64,
width: f64,
}
impl AsymLineReturn {
fn draw(&self, context: &Context) {
match self.orientation {
gtk::Orientation::Horizontal => {
context.move_to(self.start_x, self.start_y);
context.line_to(self.start_x + self.start_length, self.start_y);
context.line_to(
self.start_x + self.start_length + self.width.abs(),
self.start_y + self.width,
);
context.line_to(
self.start_x + self.start_length + self.width.abs() + self.center_length,
self.start_y + self.width,
);
context.line_to(
self.start_x
+ self.start_length
+ self.width.abs()
+ self.center_length
+ (self.width.abs() / 2.),
self.start_y + self.width / 2.,
);
context.line_to(
self.start_x
+ self.start_length
+ self.width.abs()
+ self.center_length
+ (self.width.abs() / 2.)
+ self.end_length,
self.start_y + self.width / 2.,
);
}
gtk::Orientation::Vertical => {
context.move_to(self.start_x, self.start_y);
context.line_to(self.start_x, self.start_y + self.start_length);
context.line_to(
self.start_x + self.width,
self.start_y + self.start_length + self.width.abs(),
);
context.line_to(
self.start_x + self.width,
self.start_y + self.start_length + self.width.abs() + self.center_length,
);
context.line_to(
self.start_x + self.width / 2.,
self.start_y
+ self.start_length
+ self.width.abs()
+ self.center_length
+ (self.width.abs() / 2.),
);
context.line_to(
self.start_x + self.width / 2.,
self.start_y
+ self.start_length
+ self.width.abs()
+ self.center_length
+ (self.width.abs() / 2.)
+ self.end_length,
);
}
_ => panic!("unknown orientation"),
}
}
}
fn main() {
let app = gtk::Application::builder()
.application_id("com.luminescent-dreams.cyberpunk-splash")
.build();
app.connect_activate(move |app| {
let window = gtk::ApplicationWindow::new(app);
window.present();
window.set_child(Some(&Splash::new("Kifu".to_owned(), "4:23".to_owned())));
});
app.run();
}