From 9542592027d7d169171328537425eb084a402084 Mon Sep 17 00:00:00 2001 From: Marrub Date: Wed, 27 Mar 2019 07:26:20 -0400 Subject: [PATCH] dynamic safe borrowing of map editor references --- source/tycho/editor.rs | 28 +++++++++++------- source/tycho/main.rs | 65 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/source/tycho/editor.rs b/source/tycho/editor.rs index d30d2b5..a7185cd 100644 --- a/source/tycho/editor.rs +++ b/source/tycho/editor.rs @@ -17,11 +17,11 @@ impl MapEditor MapEditor::Closed } - /// Creates a new empty map. + /// Opens the editor with a new empty map. #[inline] - pub fn new_opened() -> Self + pub fn open_new(&mut self) { - MapEditor::Opened(MapEditorState::default()) + *self = MapEditor::Opened(MapEditorState::default()); } /// Draws the screen for this editor state. @@ -31,17 +31,23 @@ impl MapEditor { match self { MapEditor::Closed => { + let tx_top = "Map Required To Proceed"; + let tx_bot = "CAS.qterm//CyberAcme Systems Inc."; + + let dw = d.w(); + let dh = d.h(); + let iw = im.w(); + let ih = im.h(); + d.clear(Color16::new(0, 0, 0)); - d.image((d.w() / 2 - im.w() / 2, d.h() / 2 - im.h() / 2), im); + d.image((dw / 2 - iw / 2, dh / 2 - ih / 2), im); - let text = "Map Required To Proceed"; - d.rect(Rect{x: 0, y: 0, w: d.w(), h: 18}, CR_DARK_RED); - d.text((4, 14), text, CR_RED); + d.rect(Rect{x: 0, y: 0, w: dw, h: 18}, CR_DARK_RED); + d.text((4, 14), tx_top, CR_RED); - let text = "CAS.qterm//CyberAcme Systems Inc."; - d.rect(Rect{x: 0, y: d.h() - 18, w: d.w(), h: 18}, CR_DARK_RED); - d.text((4, d.h() - 4), text, CR_RED); + d.rect(Rect{x: 0, y: dh - 18, w: dw, h: 18}, CR_DARK_RED); + d.text((4, dh - 4), tx_bot, CR_RED); } MapEditor::Opened(_st) => { d.clear(Color16::new(0, 0, 0)); @@ -50,6 +56,7 @@ impl MapEditor } /// Returns `true` if `self` is closed. + #[allow(dead_code)] #[inline] pub fn is_closed(&self) -> bool { @@ -60,6 +67,7 @@ impl MapEditor } /// Returns `true` if `self` is opened. + #[allow(dead_code)] #[inline] pub fn is_opened(&self) -> bool { diff --git a/source/tycho/main.rs b/source/tycho/main.rs index 73e2e6a..d7cc23a 100644 --- a/source/tycho/main.rs +++ b/source/tycho/main.rs @@ -1,8 +1,7 @@ mod editor; mod interfaces; -use crate::{editor::MapEditor, - interfaces::*}; +use crate::interfaces::*; use gdk_pixbuf_sys::*; use gdk_sys::*; use gio_sys::*; @@ -10,14 +9,14 @@ use glib_sys::*; use gobject_sys::*; use gtk_sys::*; use maraiah::{c_str, durandal::ffi}; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; /// Called whne the application activates in order to set everything up. unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: 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 *mut MapEditor); + let edit = Rc::from_raw(edit as *const MapEditorRef); setup_css(); @@ -35,14 +34,14 @@ unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: gpointer) } /// Sets up the map view window's drawing area. -unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) +unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) { struct RenderState { im_nomap: *mut GdkPixbuf, ax: *mut GtkAdjustment, ay: *mut GtkAdjustment, - edit: Rc, + edit: Rc, } /// Callback to finalize the drawing area. @@ -78,13 +77,18 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) let im = CrImage(rend.im_nomap); let dr = CrDrawArea::new(ctx, w, h); - rend.edit.draw(&dr, &im); + rend.edit.borrow().draw(&dr, &im); 1 } let wid: *mut GtkDrawingArea = get_obj(b, c_str!("draw-area")); + { + let mut edit = edit.borrow_mut(); + edit.call.push(Box::new(move || gtk_widget_queue_draw(wid as _))); + } + let ax: *mut GtkAdjustment = get_obj(b, c_str!("adj-map-horz")); let ay: *mut GtkAdjustment = get_obj(b, c_str!("adj-map-vert")); @@ -214,7 +218,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, app: *mut GtkApplication, - edit: Rc) + edit: Rc) { /// Callback to close the window when the "Quit" button is pressed. unsafe extern "C" fn c_quit_act(_: *mut GtkWidget, win: gpointer) @@ -225,8 +229,9 @@ unsafe fn setup_win_main(b: *mut GtkBuilder, /// Callback to create a new editor state when the "New" button is pressed. unsafe extern "C" fn c_new_act(_: *mut GtkWidget, edit: gpointer) { - let edit = edit as *mut MapEditor; - let edit = &mut *edit; + let edit = edit as *const MapEditorRef; + let edit = &*edit; + let mut edit = edit.borrow_mut(); if edit.is_opened() { let titl = c_str!("Confirm"); @@ -238,12 +243,14 @@ unsafe fn setup_win_main(b: *mut GtkBuilder, } } - *edit = MapEditor::new_opened(); + edit.open_new(); + edit.cause_update(); } /// Callback to finalize the editor state reference. unsafe extern "C" fn c_new_done(_: *mut GtkWidget, edit: gpointer) { + let edit = edit as *const MapEditorRef; Rc::from_raw(edit); } @@ -376,7 +383,10 @@ fn main() g_static_resource_init(&mut resource); // create a container for the editor state - let edit = Rc::new(MapEditor::new_closed()); + let edit = MapEditor{edit: editor::MapEditor::new_closed(), + call: Vec::new(), + done: Vec::new()}; + let edit = Rc::new(RefCell::new(edit)); let eptr = Rc::into_raw(edit.clone()); // create and run the app @@ -398,4 +408,35 @@ fn main() } } +impl MapEditor +{ + fn cause_update(&mut self) {for cb in &mut self.call {cb();}} +} + +impl Drop for MapEditor +{ + fn drop(&mut self) {for cb in &mut self.done {cb();}} +} + +impl std::ops::Deref for MapEditor +{ + type Target = editor::MapEditor; + + fn deref(&self) -> &editor::MapEditor {&self.edit} +} + +impl std::ops::DerefMut for MapEditor +{ + fn deref_mut(&mut self) -> &mut editor::MapEditor {&mut self.edit} +} + +struct MapEditor +{ + edit: editor::MapEditor, + call: Vec>, + done: Vec>, +} + +type MapEditorRef = RefCell; + // EOF