use droppable structure for unref things
parent
75e354a16b
commit
b8e624fecd
|
@ -8,7 +8,7 @@ use glib_sys::*;
|
|||
use gobject_sys::*;
|
||||
use gtk_sys::*;
|
||||
use maraiah::{c_str, durandal::ffi};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use std::{cell::RefCell, marker::PhantomData, rc::Rc};
|
||||
|
||||
/// Called when the application activates in order to set everything up.
|
||||
unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: gpointer)
|
||||
|
@ -20,40 +20,32 @@ unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: gpointer)
|
|||
setup_css();
|
||||
|
||||
let path = c_str!("/net/greyserv/maraiah/tycho/ui");
|
||||
let b = gtk_builder_new_from_resource(path);
|
||||
let b = Refc::new(gtk_builder_new_from_resource(path));
|
||||
|
||||
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());
|
||||
|
||||
g_object_unref(b as _);
|
||||
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());
|
||||
}
|
||||
|
||||
/// Sets up the map view window's drawing area.
|
||||
unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc<MapEditorRef>)
|
||||
unsafe fn setup_draw_area(b: &Refc<GtkBuilder>, edit: Rc<MapEditorRef>)
|
||||
{
|
||||
/// All of the state necessary for the drawing area.
|
||||
struct RenderState
|
||||
{
|
||||
im_nomap: *mut GdkPixbuf,
|
||||
ax: *mut GtkAdjustment,
|
||||
ay: *mut GtkAdjustment,
|
||||
im_nomap: Refc<'static, GdkPixbuf>,
|
||||
ax: Refc<'static, GtkAdjustment>,
|
||||
ay: Refc<'static, GtkAdjustment>,
|
||||
edit: Rc<MapEditorRef>,
|
||||
}
|
||||
|
||||
/// Callback to finalize the drawing area.
|
||||
unsafe extern "C" fn c_done(_: *mut GtkWidget, rend: gpointer)
|
||||
{
|
||||
let rend = Box::from_raw(rend as *mut RenderState);
|
||||
|
||||
g_object_unref(rend.im_nomap as gpointer as _);
|
||||
g_object_unref(rend.ax as _);
|
||||
g_object_unref(rend.ay as _);
|
||||
|
||||
// data is dropped and freed here
|
||||
Box::from_raw(rend as *mut RenderState);
|
||||
}
|
||||
|
||||
/// Callback to draw on the drawing area.
|
||||
|
@ -68,13 +60,13 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc<MapEditorRef>)
|
|||
let w = f64::from(gtk_widget_get_allocated_width(wid));
|
||||
let h = f64::from(gtk_widget_get_allocated_height(wid));
|
||||
|
||||
gtk_adjustment_set_lower(rend.ax, 0.0);
|
||||
gtk_adjustment_set_upper(rend.ax, w);
|
||||
gtk_adjustment_set_lower(*rend.ax, 0.0);
|
||||
gtk_adjustment_set_upper(*rend.ax, w);
|
||||
|
||||
gtk_adjustment_set_lower(rend.ay, 0.0);
|
||||
gtk_adjustment_set_upper(rend.ay, h);
|
||||
gtk_adjustment_set_lower(*rend.ay, 0.0);
|
||||
gtk_adjustment_set_upper(*rend.ay, h);
|
||||
|
||||
let im = CrImage(rend.im_nomap);
|
||||
let im = CrImage(*rend.im_nomap);
|
||||
let mut dr = CrDrawArea::new(ctx, w, h);
|
||||
|
||||
rend.edit.borrow().draw(&mut dr, &im);
|
||||
|
@ -87,13 +79,14 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc<MapEditorRef>)
|
|||
edit.borrow_mut().set_draw(wid as _);
|
||||
|
||||
// get all of the necessary state and related objects
|
||||
let ax: *mut GtkAdjustment = get_obj(b, c_str!("adj-map-horz"));
|
||||
let ay: *mut GtkAdjustment = get_obj(b, c_str!("adj-map-vert"));
|
||||
let ax = Refc::<GtkAdjustment>::new(get_obj(b, c_str!("adj-map-horz")));
|
||||
let ay = Refc::<GtkAdjustment>::new(get_obj(b, c_str!("adj-map-vert")));
|
||||
|
||||
g_object_ref(ax as _);
|
||||
g_object_ref(ay as _);
|
||||
g_object_ref(*ax as _);
|
||||
g_object_ref(*ay as _);
|
||||
|
||||
let im_nomap = load_img(c_str!("/net/greyserv/maraiah/tycho/tycho1.png"));
|
||||
let im_nomap = Refc::new(im_nomap);
|
||||
|
||||
let rend = RenderState{im_nomap, ax, ay, edit};
|
||||
let rend = Box::into_raw(Box::new(rend));
|
||||
|
@ -103,7 +96,7 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc<MapEditorRef>)
|
|||
}
|
||||
|
||||
/// Sets up the map view window.
|
||||
unsafe fn setup_win_map_view(b: *mut GtkBuilder)
|
||||
unsafe fn setup_win_map_view(b: &Refc<GtkBuilder>)
|
||||
{
|
||||
let win: *mut GtkWindow = get_obj(b, c_str!("win-map-view"));
|
||||
let btn: *mut GtkMenuItem = get_obj(b, c_str!("btn-show-map-view"));
|
||||
|
@ -113,7 +106,7 @@ unsafe fn setup_win_map_view(b: *mut GtkBuilder)
|
|||
}
|
||||
|
||||
/// Sets up the map tools window.
|
||||
unsafe fn setup_win_map_tools(b: *mut GtkBuilder)
|
||||
unsafe fn setup_win_map_tools(b: &Refc<GtkBuilder>)
|
||||
{
|
||||
let win: *mut GtkWindow = get_obj(b, c_str!("win-map-tools"));
|
||||
let btn: *mut GtkMenuItem = get_obj(b, c_str!("btn-show-map-tools"));
|
||||
|
@ -123,7 +116,7 @@ unsafe fn setup_win_map_tools(b: *mut GtkBuilder)
|
|||
}
|
||||
|
||||
/// Sets up the map properties window.
|
||||
unsafe fn setup_win_map_prop(b: *mut GtkBuilder)
|
||||
unsafe fn setup_win_map_prop(b: &Refc<GtkBuilder>)
|
||||
{
|
||||
let win: *mut GtkWindow = get_obj(b, c_str!("win-map-prop"));
|
||||
let btn: *mut GtkMenuItem = get_obj(b, c_str!("btn-show-map-prop"));
|
||||
|
@ -133,7 +126,7 @@ unsafe fn setup_win_map_prop(b: *mut GtkBuilder)
|
|||
}
|
||||
|
||||
/// Sets up the about dialogue.
|
||||
unsafe fn setup_about_dlg(b: *mut GtkBuilder)
|
||||
unsafe fn setup_about_dlg(b: &Refc<GtkBuilder>)
|
||||
{
|
||||
/// Callback to show the dialogue when the "About" button is pressed, and
|
||||
/// hide it when the "Close" button is pressed on it.
|
||||
|
@ -149,20 +142,19 @@ unsafe fn setup_about_dlg(b: *mut GtkBuilder)
|
|||
let it = env!("CARGO_PKG_AUTHORS").split(';');
|
||||
let mut v = ffi::CStringVec::new_from_iter(it).unwrap();
|
||||
let img = load_img(c_str!("/net/greyserv/maraiah/tycho/tycho2.png"));
|
||||
let img = Refc::new(img);
|
||||
|
||||
gtk_about_dialog_set_authors(dlg, v.as_mut_ptr());
|
||||
gtk_about_dialog_set_version(dlg, c_str!(env!("CARGO_PKG_VERSION")));
|
||||
gtk_about_dialog_set_website(dlg, c_str!(env!("CARGO_PKG_HOMEPAGE")));
|
||||
gtk_about_dialog_set_logo(dlg, img);
|
||||
gtk_about_dialog_set_logo(dlg, *img);
|
||||
|
||||
connect_hide(dlg as _);
|
||||
connect(btn as _, c_str!("activate"), c_show_act as _, dlg as _);
|
||||
|
||||
g_object_unref(img as gpointer as _);
|
||||
}
|
||||
|
||||
/// Sets up explicit window finalization for the main window.
|
||||
unsafe fn setup_explicit_drop(b: *mut GtkBuilder, win: *mut GtkWindow)
|
||||
unsafe fn setup_explicit_drop(b: &Refc<GtkBuilder>, win: *mut GtkWindow)
|
||||
{
|
||||
/// Callback to explicitly finalize all windows on exit.
|
||||
unsafe extern "C" fn c_done(_: *mut GtkWidget, exp_del: gpointer)
|
||||
|
@ -179,7 +171,7 @@ unsafe fn setup_explicit_drop(b: *mut GtkBuilder, win: *mut GtkWindow)
|
|||
let mut exp_del = Vec::new();
|
||||
|
||||
// so, we get all of the objects from the builder, and iterate through them
|
||||
let head = gtk_builder_get_objects(b);
|
||||
let head = gtk_builder_get_objects(**b);
|
||||
let mut lst = &*head;
|
||||
|
||||
loop {
|
||||
|
@ -214,7 +206,7 @@ unsafe fn setup_explicit_drop(b: *mut GtkBuilder, win: *mut GtkWindow)
|
|||
}
|
||||
|
||||
/// Sets up the main menu window.
|
||||
unsafe fn setup_win_main(b: *mut GtkBuilder,
|
||||
unsafe fn setup_win_main(b: &Refc<GtkBuilder>,
|
||||
app: *mut GtkApplication,
|
||||
edit: Rc<MapEditorRef>)
|
||||
{
|
||||
|
@ -277,14 +269,12 @@ unsafe fn setup_win_main(b: *mut GtkBuilder,
|
|||
unsafe fn setup_css()
|
||||
{
|
||||
let path = c_str!("/net/greyserv/maraiah/tycho/css");
|
||||
let css = gtk_css_provider_new();
|
||||
gtk_css_provider_load_from_resource(css, path);
|
||||
let css = Refc::new(gtk_css_provider_new());
|
||||
gtk_css_provider_load_from_resource(*css, path);
|
||||
|
||||
let scr = gdk_screen_get_default();
|
||||
let pri = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32;
|
||||
gtk_style_context_add_provider_for_screen(scr, css as _, pri);
|
||||
|
||||
g_object_unref(css as _);
|
||||
gtk_style_context_add_provider_for_screen(scr, *css as _, pri);
|
||||
}
|
||||
|
||||
/// Runs a modal OK/Cancel dialogue.
|
||||
|
@ -343,9 +333,9 @@ unsafe fn connect_show(btn: *mut GtkWidget, wid: *mut GtkWidget)
|
|||
}
|
||||
|
||||
/// Gets an object from a `GtkBuilder`.
|
||||
unsafe fn get_obj<T>(b: *mut GtkBuilder, name: ffi::NT) -> *mut T
|
||||
unsafe fn get_obj<T>(b: &Refc<GtkBuilder>, name: ffi::NT) -> *mut T
|
||||
{
|
||||
let obj = gtk_builder_get_object(b, name);
|
||||
let obj = gtk_builder_get_object(**b, name);
|
||||
obj as _
|
||||
}
|
||||
|
||||
|
@ -388,14 +378,14 @@ fn main()
|
|||
|
||||
// create and run the app
|
||||
let name = c_str!("net.greyserv.maraiah.tycho");
|
||||
let app = gtk_application_new(name, 0);
|
||||
let app = Refc::new(gtk_application_new(name, 0));
|
||||
|
||||
connect(app as _, c_str!("activate"), app_activate as _, eptr as _);
|
||||
connect(*app as _, c_str!("activate"), app_activate as _, eptr as _);
|
||||
|
||||
g_application_run(app as _, 0, ffi::null_mut());
|
||||
g_application_run(*app as _, 0, ffi::null_mut());
|
||||
|
||||
// ok, clean up all this crap now
|
||||
g_object_unref(app as _);
|
||||
drop(app);
|
||||
|
||||
assert_eq!(Rc::strong_count(&edit), 1);
|
||||
drop(edit);
|
||||
|
@ -405,4 +395,32 @@ fn main()
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for Refc<'_, T>
|
||||
{
|
||||
type Target = *mut T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {&self.p}
|
||||
}
|
||||
|
||||
impl<T> Drop for Refc<'_, T>
|
||||
{
|
||||
fn drop(&mut self)
|
||||
{
|
||||
unsafe {
|
||||
g_object_unref(self.p as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> 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
|
||||
|
|
Loading…
Reference in New Issue