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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Generated with glade 3.22.1
|
<!-- 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
|
Author: Alison Sanderson
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
@ -31,7 +9,6 @@ Author: Alison Sanderson
|
||||||
<!-- interface-license-type mit -->
|
<!-- interface-license-type mit -->
|
||||||
<!-- interface-name Maraiah Tycho -->
|
<!-- interface-name Maraiah Tycho -->
|
||||||
<!-- interface-description Tycho map editor for Maraiah. -->
|
<!-- interface-description Tycho map editor for Maraiah. -->
|
||||||
<!-- interface-copyright 2018-2019 Alison Sanderson -->
|
|
||||||
<!-- interface-authors Alison Sanderson -->
|
<!-- interface-authors Alison Sanderson -->
|
||||||
<object class="GtkAdjustment" id="adj-map-horz">
|
<object class="GtkAdjustment" id="adj-map-horz">
|
||||||
<property name="upper">100</property>
|
<property name="upper">100</property>
|
||||||
|
|
|
@ -8,6 +8,7 @@ use gtk_sys::*;
|
||||||
use maraiah::{c_str,
|
use maraiah::{c_str,
|
||||||
durandal::{ffi, image::*},
|
durandal::{ffi, image::*},
|
||||||
rozinante::{draw::*, editor}};
|
rozinante::{draw::*, editor}};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Converts a `Color` to a `f64` triple.
|
/// Converts a `Color` to a `f64` triple.
|
||||||
fn flt_color(cr: impl Color) -> (f64, f64, f64)
|
fn flt_color(cr: impl Color) -> (f64, f64, f64)
|
||||||
|
@ -129,35 +130,7 @@ impl MapEditor
|
||||||
pub fn cause_update(&mut self)
|
pub fn cause_update(&mut self)
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
gtk_widget_queue_draw(self.draw);
|
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 _);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,6 +149,32 @@ impl std::ops::DerefMut for MapEditor
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {&mut self.edit}
|
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`.
|
/// An image for a `CrDrawArea`.
|
||||||
pub struct CrImage(pub *const GdkPixbuf);
|
pub struct CrImage(pub *const GdkPixbuf);
|
||||||
|
|
||||||
|
@ -190,11 +189,18 @@ pub struct CrDrawArea
|
||||||
/// Specialized map editor which has callbacks for frontend purposes.
|
/// Specialized map editor which has callbacks for frontend purposes.
|
||||||
pub struct MapEditor
|
pub struct MapEditor
|
||||||
{
|
{
|
||||||
edit: editor::MapEditor,
|
pub edit: editor::MapEditor,
|
||||||
draw: *mut GtkWidget,
|
pub draw: Refc<'static, GtkWidget>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A runtime reference to the map editor.
|
/// A runtime reference to the map editor.
|
||||||
pub type MapEditorRef = std::cell::RefCell<MapEditor>;
|
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
|
// EOF
|
||||||
|
|
|
@ -8,7 +8,7 @@ use glib_sys::*;
|
||||||
use gobject_sys::*;
|
use gobject_sys::*;
|
||||||
use gtk_sys::*;
|
use gtk_sys::*;
|
||||||
use maraiah::{c_str, durandal::ffi};
|
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 ACTIVATE: ffi::NT = c_str!("activate");
|
||||||
const APP_ID: ffi::NT = c_str!("net.greyserv.maraiah.tycho");
|
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");
|
const PATH_CSS: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/css");
|
||||||
|
|
||||||
/// Called when the application activates in order to set everything up.
|
/// 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
|
/// Callback to finalize the reference.
|
||||||
// the end of this function.
|
unsafe extern "C" fn c_done(_: *mut GtkWidget, ptr: gpointer)
|
||||||
let edit = Rc::from_raw(edit as *const MapEditorRef);
|
{
|
||||||
|
let edit = Rc::from_raw(ptr as *const MapEditorRef);
|
||||||
setup_css();
|
assert_eq!(Rc::strong_count(&edit), 1);
|
||||||
|
}
|
||||||
|
|
||||||
let b = Refc::new(gtk_builder_new_from_resource(PATH_BUILDER));
|
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_draw_area(&b, edit.clone());
|
||||||
setup_win_map_view(&b);
|
setup_win_map_view(&b);
|
||||||
setup_win_map_tools(&b);
|
setup_win_map_tools(&b);
|
||||||
setup_win_map_prop(&b);
|
setup_win_map_prop(&b);
|
||||||
setup_about_dlg(&b);
|
setup_about_dlg(&b);
|
||||||
setup_win_main(&b, app, edit.clone());
|
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.
|
/// 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"));
|
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
|
// get all of the necessary state and related objects
|
||||||
let ax = Refc::new(get_obj::<GtkAdjustment>(b, c_str!("adj-map-horz")));
|
let ax = Refc::own(get_obj(b, c_str!("adj-map-horz")));
|
||||||
let ay = Refc::new(get_obj::<GtkAdjustment>(b, c_str!("adj-map-vert")));
|
let ay = Refc::own(get_obj(b, c_str!("adj-map-vert")));
|
||||||
|
|
||||||
g_object_ref(*ax as _);
|
|
||||||
g_object_ref(*ay as _);
|
|
||||||
|
|
||||||
let im_nomap = Refc::new(load_img(IM_NOMAP));
|
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
|
// 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);
|
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);
|
connect(btn, ACTIVATE, c_show_act as _, wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connects a reference-counted object to a widget.
|
/// Connects the map editor reference to a widget.
|
||||||
unsafe fn connect_ref<T, U>(obj: *mut T, rc: Rc<U>) -> *const U
|
unsafe fn connect_ref<T>(obj: *mut T, rc: Rc<MapEditorRef>)
|
||||||
|
-> *const MapEditorRef
|
||||||
{
|
{
|
||||||
/// Callback to finalize the reference.
|
/// 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);
|
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!
|
// init it, now we can use it throughout the entire app without copying!
|
||||||
g_static_resource_init(&mut resource);
|
g_static_resource_init(&mut resource);
|
||||||
|
|
||||||
// create a container for the editor state
|
{
|
||||||
let edit = MapEditor::default();
|
// create and run the app
|
||||||
let edit = RefCell::new(edit);
|
let app = Refc::new(gtk_application_new(APP_ID, 0));
|
||||||
let edit = Rc::new(edit);
|
|
||||||
let eptr = Rc::into_raw(edit.clone());
|
|
||||||
|
|
||||||
// create and run the app
|
connect(*app, ACTIVATE, app_activate as _, ffi::null_void());
|
||||||
let app = Refc::new(gtk_application_new(APP_ID, 0));
|
|
||||||
|
|
||||||
connect(*app, ACTIVATE, app_activate as _, eptr);
|
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
|
|
||||||
drop(app);
|
|
||||||
|
|
||||||
assert_eq!(Rc::strong_count(&edit), 1);
|
|
||||||
drop(edit);
|
|
||||||
|
|
||||||
// deinit the "static" data, and everything will be done
|
// deinit the "static" data, and everything will be done
|
||||||
g_static_resource_fini(&mut resource);
|
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
|
// EOF
|
||||||
|
|
Loading…
Reference in New Issue