move editor to app activation so it can be initialized correctly

gui-branch
an 2019-04-02 15:34:02 -04:00
parent 6bc4ca36f4
commit f4b0e37542
3 changed files with 67 additions and 117 deletions

View File

@ -1,28 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1
The MIT License (MIT)
Copyright (c) 2018-2019 Alison Sanderson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Author: Alison Sanderson
-->
@ -31,7 +9,6 @@ Author: Alison Sanderson
<!-- interface-license-type mit -->
<!-- interface-name Maraiah Tycho -->
<!-- interface-description Tycho map editor for Maraiah. -->
<!-- interface-copyright 2018-2019 Alison Sanderson -->
<!-- interface-authors Alison Sanderson -->
<object class="GtkAdjustment" id="adj-map-horz">
<property name="upper">100</property>

View File

@ -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<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>
{
/// 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<MapEditor>;
/// A GObject owned pointer.
pub struct Refc<'a, T>
{
p: *mut T,
l: PhantomData<&'a *mut T>,
}
// EOF

View File

@ -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<GtkBuilder>, edit: Rc<MapEditorRef>)
let wid = get_obj::<GtkDrawingArea>(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::<GtkAdjustment>(b, c_str!("adj-map-horz")));
let ay = Refc::new(get_obj::<GtkAdjustment>(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<GtkBuilder>,
}
// set up main window
let win = get_obj::<GtkWindow>(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<T, U>(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<T, U>(obj: *mut T, rc: Rc<U>) -> *const U
/// Connects the map editor reference to a widget.
unsafe fn connect_ref<T>(obj: *mut T, rc: Rc<MapEditorRef>)
-> *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<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