Maraiah/source/tycho/main.rs

180 lines
5.2 KiB
Rust

mod hiddenprotocol;
mod noroom;
use crate::{hiddenprotocol::*, noroom::*};
use gio::prelude::*;
use gtk::prelude::*;
use maraiah::durandal::err::*;
use std::{os::raw::c_char, rc::Rc};
const DATA_NAME: *const c_char = b"tycho data\0".as_ptr() as *const c_char;
fn hide_on_delete(win: &gtk::Window, _: &gdk::Event) -> Inhibit
{
win.hide();
Inhibit(true)
}
fn mk_draw_area(b: &gtk::Builder)
{
let area: gtk::DrawingArea = get_obj(b, "draw-area");
let ax: gtk::Adjustment = get_obj(b, "adj-map-horz");
let ay: gtk::Adjustment = get_obj(b, "adj-map-vert");
let im = CairoPixbuf(load_img("/net/greyserv/maraiah/tycho/tycho1"));
area.connect_draw(move |area, cr| {
let w = f64::from(area.get_allocated_width());
let h = f64::from(area.get_allocated_height());
ax.set_lower(0.0);
ax.set_upper(w);
ay.set_lower(0.0);
ay.set_upper(h);
let d = CairoDrawArea::new(cr.clone(), w, h);
draw_map_none(&d, &im);
Inhibit(true)
});
}
fn run_app(app: &gtk::Application)
{
let b = &gtk::Builder::new_from_resource("/net/greyserv/maraiah/tycho/ui");
let prv = gtk::CssProvider::new();
prv.load_from_resource("/net/greyserv/maraiah/tycho/css");
let scr = gdk::Screen::get_default().expect("no screen found");
let pri = gtk::STYLE_PROVIDER_PRIORITY_APPLICATION;
gtk::StyleContext::add_provider_for_screen(&scr, &prv, pri);
let app_ = app.downgrade();
let btn: gtk::MenuItem = get_obj(b, "btn-quit");
btn.connect_activate(move |_| {
if let Some(app) = app_.upgrade() {
app.quit();
}
});
let btn: gtk::MenuItem = get_obj(b, "btn-about");
let win: gtk::AboutDialog = get_obj(b, "win-about");
btn.connect_activate(move |_| {win.run(); win.hide();});
let btn: gtk::MenuItem = get_obj(b, "btn-show-map-view");
let win: gtk::Window = get_obj(b, "win-map-view");
win.connect_delete_event(hide_on_delete);
btn.connect_activate(move |_| win.show_all());
let btn: gtk::MenuItem = get_obj(b, "btn-show-map-tools");
let win: gtk::Window = get_obj(b, "win-map-tools");
win.connect_delete_event(hide_on_delete);
btn.connect_activate(move |_| win.show_all());
let btn: gtk::MenuItem = get_obj(b, "btn-show-map-prop");
let win: gtk::Window = get_obj(b, "win-map-prop");
win.connect_delete_event(hide_on_delete);
btn.connect_activate(move |_| win.show_all());
mk_draw_area(b);
let win: gtk::AboutDialog = get_obj(b, "win-about");
win.set_authors(&env!("CARGO_PKG_AUTHORS").split(';').collect::<Vec<_>>());
win.set_version(env!("CARGO_PKG_VERSION"));
win.set_website(env!("CARGO_PKG_HOMEPAGE"));
win.set_logo(&load_img("/net/greyserv/maraiah/tycho/tycho2"));
let win: gtk::Window = get_obj(b, "win-first-start");
win.show_all();
let win: gtk::Window = get_obj(b, "win-main");
win.set_application(app);
win.show_all();
}
fn load_img(path: &'static str) -> gdk_pixbuf::Pixbuf
{
gdk_pixbuf::Pixbuf::new_from_resource(path).unwrap()
}
fn get_obj<T>(b: &gtk::Builder, name: &str) -> T
where T: glib::object::IsA<glib::object::Object>
{
b.get_object(name).unwrap()
}
fn main() -> ResultS<()>
{
// get jacked, punk. opaque data structures are for nerds.
const RESOURCE_DATA: &[u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/resources"));
// first we create the static resource header, which is really simple
let mut static_resource =
gio_sys::GStaticResource{data: RESOURCE_DATA.as_ptr(),
data_len: RESOURCE_DATA.len(),
resource: std::ptr::null_mut(),
next: std::ptr::null_mut(),
padding: std::ptr::null_mut()};
// init it, now we can use it throughout the entire app without copying!
unsafe {
gio_sys::g_static_resource_init(&mut static_resource);
}
let ret = {
// create the application first
let app = gtk::Application::new("net.greyserv.maraiah.tycho",
gio::ApplicationFlags::empty())?;
app.connect_activate(run_app);
// then we can attach the editor state to the app's hashtable
let app_ptr = app.clone().upcast::<glib::Object>().as_ptr();
let dat = Rc::new(None::<MapEditorState>);
unsafe {
// this ref will be dropped after the app is run
let ptr = Rc::into_raw(dat.clone()) as glib_sys::gpointer;
gobject_sys::g_object_set_data(app_ptr, DATA_NAME, ptr);
}
// run the application and save the return
let ret = if app.run(&[]) == 0 {
Ok(())
} else {
Err(err_msg("bad return"))
};
// unref the editor state so it will go away
unsafe {
let ptr = gobject_sys::g_object_get_data(app_ptr, DATA_NAME);
let ptr = Rc::from_raw(ptr);
std::mem::drop(ptr);
}
// destroy the editor state first, and make sure there are no dangling
// references to the application.
std::mem::drop(dat);
assert_eq!(app.ref_count(), 1);
ret
};
// finally, deinit the "static" data, and everything will be done
unsafe {
gio_sys::g_static_resource_fini(&mut static_resource);
}
ret
}
// EOF