180 lines
5.2 KiB
Rust
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: >k::Window, _: &gdk::Event) -> Inhibit
|
|
{
|
|
win.hide();
|
|
Inhibit(true)
|
|
}
|
|
|
|
fn mk_draw_area(b: >k::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: >k::Application)
|
|
{
|
|
let b = >k::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: >k::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
|