move editor to app activation so it can be initialized correctly
parent
6bc4ca36f4
commit
f4b0e37542
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue