diff --git a/source/tycho/data/ui.xml b/source/tycho/data/ui.xml index 70b0c46..b25fa04 100644 --- a/source/tycho/data/ui.xml +++ b/source/tycho/data/ui.xml @@ -1,28 +1,6 @@ @@ -31,7 +9,6 @@ Author: Alison Sanderson - 100 diff --git a/source/tycho/interfaces.rs b/source/tycho/interfaces.rs index e6cc1bd..4f19ce2 100644 --- a/source/tycho/interfaces.rs +++ b/source/tycho/interfaces.rs @@ -8,6 +8,7 @@ use gtk_sys::*; use maraiah::{c_str, durandal::{ffi, image::*}, rozinante::{draw::*, editor}}; +use std::marker::PhantomData; /// Converts a `Color` to a `f64` triple. fn flt_color(cr: impl Color) -> (f64, f64, f64) @@ -129,35 +130,7 @@ impl MapEditor pub fn cause_update(&mut self) { unsafe { - gtk_widget_queue_draw(self.draw); - } - } - - /// Sets the drawing area widget. - pub fn set_draw(&mut self, draw: *mut GtkWidget) - { - self.draw = draw; - unsafe { - g_object_ref(self.draw as _); - } - } -} - -impl Default for MapEditor -{ - fn default() -> Self - { - Self{edit: editor::MapEditor::default(), - draw: ffi::null_mut()} - } -} - -impl Drop for MapEditor -{ - fn drop(&mut self) - { - unsafe { - g_object_unref(self.draw as _); + gtk_widget_queue_draw(*self.draw); } } } @@ -176,6 +149,32 @@ impl std::ops::DerefMut for MapEditor fn deref_mut(&mut self) -> &mut Self::Target {&mut self.edit} } +impl std::ops::Deref for Refc<'_, T> +{ + type Target = *mut T; + + fn deref(&self) -> &Self::Target {&self.p} +} + +impl Drop for Refc<'_, T> +{ + fn drop(&mut self) + { + unsafe { + g_object_unref(self.p as _); + } + } +} + +impl Refc<'_, T> +{ + /// Creates a new `Refc` which will own an already referenced object. + pub const fn new(p: *mut T) -> Self {Self{p, l: PhantomData}} + + /// Creates a new `Refc` which will hold a reference to the object. + pub fn own(p: *mut T) -> Self {unsafe {g_object_ref(p as _);} Self::new(p)} +} + /// An image for a `CrDrawArea`. pub struct CrImage(pub *const GdkPixbuf); @@ -190,11 +189,18 @@ pub struct CrDrawArea /// Specialized map editor which has callbacks for frontend purposes. pub struct MapEditor { - edit: editor::MapEditor, - draw: *mut GtkWidget, + pub edit: editor::MapEditor, + pub draw: Refc<'static, GtkWidget>, } /// A runtime reference to the map editor. pub type MapEditorRef = std::cell::RefCell; +/// A GObject owned pointer. +pub struct Refc<'a, T> +{ + p: *mut T, + l: PhantomData<&'a *mut T>, +} + // EOF diff --git a/source/tycho/main.rs b/source/tycho/main.rs index b14d499..b5742bf 100644 --- a/source/tycho/main.rs +++ b/source/tycho/main.rs @@ -8,7 +8,7 @@ use glib_sys::*; use gobject_sys::*; use gtk_sys::*; use maraiah::{c_str, durandal::ffi}; -use std::{cell::RefCell, marker::PhantomData, rc::Rc}; +use std::{cell::RefCell, rc::Rc}; const ACTIVATE: ffi::NT = c_str!("activate"); const APP_ID: ffi::NT = c_str!("net.greyserv.maraiah.tycho"); @@ -21,22 +21,31 @@ const PATH_BUILDER: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/ui"); const PATH_CSS: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/css"); /// Called when the application activates in order to set everything up. -unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: gpointer) +unsafe extern "C" fn app_activate(app: *mut GtkApplication, _: gpointer) { - // this ref will be cloned around a bit, but will ultimately be dropped at - // the end of this function. - let edit = Rc::from_raw(edit as *const MapEditorRef); - - setup_css(); + /// Callback to finalize the reference. + unsafe extern "C" fn c_done(_: *mut GtkWidget, ptr: gpointer) + { + let edit = Rc::from_raw(ptr as *const MapEditorRef); + assert_eq!(Rc::strong_count(&edit), 1); + } let b = Refc::new(gtk_builder_new_from_resource(PATH_BUILDER)); + let edit = MapEditor{edit: Default::default(), + draw: Refc::own(get_obj(&b, c_str!("draw-area")))}; + let edit = RefCell::new(edit); + let edit = Rc::new(edit); + + setup_css(); setup_draw_area(&b, edit.clone()); setup_win_map_view(&b); setup_win_map_tools(&b); setup_win_map_prop(&b); setup_about_dlg(&b); setup_win_main(&b, app, edit.clone()); + + connect(app, c_str!("shutdown"), c_done as _, Rc::into_raw(edit)); } /// Sets up the map view window's drawing area. @@ -84,14 +93,9 @@ unsafe fn setup_draw_area(b: &Refc, edit: Rc) let wid = get_obj::(b, c_str!("draw-area")); - edit.borrow_mut().set_draw(wid as _); - // get all of the necessary state and related objects - let ax = Refc::new(get_obj::(b, c_str!("adj-map-horz"))); - let ay = Refc::new(get_obj::(b, c_str!("adj-map-vert"))); - - g_object_ref(*ax as _); - g_object_ref(*ay as _); + let ax = Refc::own(get_obj(b, c_str!("adj-map-horz"))); + let ay = Refc::own(get_obj(b, c_str!("adj-map-vert"))); let im_nomap = Refc::new(load_img(IM_NOMAP)); @@ -268,7 +272,7 @@ unsafe fn setup_win_main(b: &Refc, } // set up main window - let win = get_obj::(b, c_str!("win-main")); + let win = get_obj(b, c_str!("win-main")); setup_explicit_drop(b, win); @@ -382,13 +386,14 @@ unsafe fn connect_show(btn: *mut T, wid: *mut U) connect(btn, ACTIVATE, c_show_act as _, wid); } -/// Connects a reference-counted object to a widget. -unsafe fn connect_ref(obj: *mut T, rc: Rc) -> *const U +/// Connects the map editor reference to a widget. +unsafe fn connect_ref(obj: *mut T, rc: Rc) + -> *const MapEditorRef { /// Callback to finalize the reference. - unsafe extern "C" fn c_done(_: *mut GtkWidget, edit: gpointer) + unsafe extern "C" fn c_done(_: *mut GtkWidget, ptr: gpointer) { - Rc::from_raw(edit as *const MapEditorRef); + Rc::from_raw(ptr as *const MapEditorRef); } let ptr = Rc::into_raw(rc); @@ -435,56 +440,18 @@ fn main() // init it, now we can use it throughout the entire app without copying! g_static_resource_init(&mut resource); - // create a container for the editor state - let edit = MapEditor::default(); - let edit = RefCell::new(edit); - let edit = Rc::new(edit); - let eptr = Rc::into_raw(edit.clone()); + { + // create and run the app + let app = Refc::new(gtk_application_new(APP_ID, 0)); - // create and run the app - let app = Refc::new(gtk_application_new(APP_ID, 0)); + connect(*app, ACTIVATE, app_activate as _, ffi::null_void()); - connect(*app, ACTIVATE, app_activate as _, eptr); - - g_application_run(*app as _, 0, ffi::null_mut()); - - // ok, clean up all this crap now - drop(app); - - assert_eq!(Rc::strong_count(&edit), 1); - drop(edit); + g_application_run(*app as _, 0, ffi::null_mut()); + } // deinit the "static" data, and everything will be done g_static_resource_fini(&mut resource); } } -impl std::ops::Deref for Refc<'_, T> -{ - type Target = *mut T; - - fn deref(&self) -> &Self::Target {&self.p} -} - -impl Drop for Refc<'_, T> -{ - fn drop(&mut self) - { - unsafe { - g_object_unref(self.p as _); - } - } -} - -impl Refc<'_, T> -{ - fn new(p: *mut T) -> Self {Self{p, l: PhantomData}} -} - -struct Refc<'a, T> -{ - p: *mut T, - l: PhantomData<&'a *mut T>, -} - // EOF