From 56df373dc10ab619f3ce3d144d58ed7934feedda Mon Sep 17 00:00:00 2001 From: Marrub Date: Mon, 13 May 2019 22:03:09 -0400 Subject: [PATCH] crap --- source/rozinante/editor.rs | 130 +--- .../rozinante/editor/{block.rs => record.rs} | 6 +- source/rozinante/editor/screen.rs | 12 + source/rozinante/editor/session.rs | 20 + source/tycho/data/ui.xml | 696 ++++++++++-------- source/tycho/interfaces/editor.rs | 140 +--- source/tycho/main.rs | 300 ++------ 7 files changed, 504 insertions(+), 800 deletions(-) rename source/rozinante/editor/{block.rs => record.rs} (70%) create mode 100644 source/rozinante/editor/screen.rs create mode 100644 source/rozinante/editor/session.rs diff --git a/source/rozinante/editor.rs b/source/rozinante/editor.rs index c3ec10a..9b3dae3 100644 --- a/source/rozinante/editor.rs +++ b/source/rozinante/editor.rs @@ -1,129 +1,7 @@ -//! Main map editor module. -//! -//! The entry point is responsible for maintaining the lifetime of the editor -//! and human interactions with it, but is otherwise not permitted to directly -//! edit it. +//! Map editor handling. -mod block; - -pub use block::*; - -use super::{color, draw::*}; -use crate::{durandal::image::*, marathon::{machdr, map}}; - -impl MapEditor -{ - /// Opens the editor with a new map. - pub fn open_new(&mut self) - { - *self = Self::default(); - } - - /// Opens the editor with an existing map. - pub fn open_buf(&mut self, b: &[u8]) - { - // TODO: handle errors gracefully - let b = &b[machdr::try_mac_header(b)..]; - let wad = map::read(b).expect("bad map file"); - - let ent = wad.entries.iter().nth(0).expect("no entries").1; - let info = ent.chunks.iter().find_map(|cnk| { - match cnk { - map::chnk::Chunk::Minf(info) => Some(info), - _ => None, - } - }).expect("no Minf chunk").clone(); - - let block = Block{info}; - - dbg!(&block); - - *self = Self{blocks: vec![block], - tools: Self::default_tools()}; - } - - /// Draws the screen for this editor state. - pub fn draw(&self, d: &mut D, im: &I) - where D: DrawArea, - I: CacheImage - { - /* - let dw = d.w(); - let dh = d.h(); - let iw = im.w(); - let ih = im.h(); - - let tx_top = "Map Required To Proceed"; - let tx_bot = "CAS.qterm//CyberAcme Systems Inc."; - - d.clear(Color16::new(0, 0, 0)); - - d.image((dw / 2 - iw / 2, dh / 2 - ih / 2), im); - - d.rect(Rect{x: 0, y: 0, w: dw, h: 18}, color::DARK_RED); - d.text((4, 0), tx_top, color::RED); - - d.rect(Rect{x: 0, y: dh - 18, w: dw, h: 18}, color::DARK_RED); - d.text((4, dh - 16), tx_bot, color::RED); - */ - - let _ = im; - - let text = &format!("{:#?}", &self); - - d.clear(Color16::new(0, 0, 0)); - d.text((0, 0), text, color::RED); - } - - // Returns the default tools. - const fn default_tools() -> (Tool, Tool) {(Tool::Points, Tool::Lines)} - - /// Returns a reference to the current block. - pub fn cur_block(&self) -> &Block {self.blocks.last().unwrap()} - - /// Pushes a new block. - pub fn push_block(&mut self, blk: Block) {self.blocks.push(blk);} - - /// Returns the current tool. - pub fn tool(&self) -> &Tool {&self.tools.0} - - /// Sets the current tool, and returns the previous one. - pub fn set_tool(&mut self, t: Tool) -> &Tool - { - self.tools.1 = self.tools.0.clone(); - self.tools.0 = t; - - &self.tools.1 - } - - /// Returns true if the current map is unclean and needs to be saved. - pub fn unclean(&self) -> bool {true} -} - -impl Default for MapEditor -{ - #[inline] - fn default() -> Self - { - Self{blocks: vec![Block::default()], tools: Self::default_tools()} - } -} - -/// The state of an opened map editor. -#[derive(Debug)] -pub struct MapEditor -{ - blocks: Vec, - tools: (Tool, Tool), -} - -/// A tool in the map editor. -#[derive(Clone, Debug)] -pub enum Tool -{ - Points, - Lines, - Polygons, -} +pub mod record; +pub mod screen; +pub mod session; // EOF diff --git a/source/rozinante/editor/block.rs b/source/rozinante/editor/record.rs similarity index 70% rename from source/rozinante/editor/block.rs rename to source/rozinante/editor/record.rs index 0b98323..1f9abc9 100644 --- a/source/rozinante/editor/block.rs +++ b/source/rozinante/editor/record.rs @@ -1,6 +1,8 @@ +//! Map editor records, or saved client state. + use crate::marathon::map; -impl Default for Block +impl Default for Record { #[inline] fn default() -> Self {Self{info: map::minf::Minf::default()}} @@ -8,7 +10,7 @@ impl Default for Block /// Copyable, versioned map state. #[derive(Clone, Debug)] -pub struct Block +pub struct Record { pub info: map::minf::Minf, } diff --git a/source/rozinante/editor/screen.rs b/source/rozinante/editor/screen.rs new file mode 100644 index 0000000..10c7425 --- /dev/null +++ b/source/rozinante/editor/screen.rs @@ -0,0 +1,12 @@ +//! Map editor screen, or current UI state. + +pub trait Screen +{ + /// Opens the editor with a new map. + fn open_new(&mut self); + + /// Opens the editor with a new map. + fn open_buf(&mut self, b: &[u8]); +} + +// EOF diff --git a/source/rozinante/editor/session.rs b/source/rozinante/editor/session.rs new file mode 100644 index 0000000..3470694 --- /dev/null +++ b/source/rozinante/editor/session.rs @@ -0,0 +1,20 @@ +//! Map editor session, or current client state. + +impl Session +{ + /// Opens the editor with a new map. + fn open_new(&mut self) + { + } + + /// Opens the editor with a new map. + fn open_buf(&mut self, b: &[u8]) + { + } +} + +struct Session +{ +} + +// EOF diff --git a/source/tycho/data/ui.xml b/source/tycho/data/ui.xml index ce97ccc..1dfc46c 100644 --- a/source/tycho/data/ui.xml +++ b/source/tycho/data/ui.xml @@ -12,32 +12,333 @@ 1 10 - + + 65535 + 1 + 10 + + False - Map View - 600 - 400 - + True + dialog + Tycho Map Editor + By Alison Sanderson. Public domain. + greetigs i am tico the of superior ai to durdumbal go shoot my soldiers because its funny or ill put you in space + Home Page + To the extent possible under law, I, Alison Sanderson, have waived all +copyright and related or neighboring rights to this Document as described by +the Creative Commons Zero license as follows: + +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + + image-loading + custom + + + + + + False + vertical + 2 + + + False + end + + + False + False + 0 + + + + + + + + + + About Screen + The about screen for Tycho. + dialog + + + + + True + False + 24 + tycho-lines + + + True + False + 24 + tycho-points + + + True + False + 24 + tycho-polys + + + False + Tycho + False + 120 + 250 + - + True - True - always - always - top-right - False + False + ttb - + True False - adj-map-horz - adj-map-vert - - + _File + True + + True False + + + True + False + Create a new project. + _New Project + True + + + + + True + False + Opens any type of project file. + _Open + True + + + + + True + False + Saves the currently open project. + _Save + True + + + + + True + False + + + + + True + False + Quit the application. + _Quit + True + + + + + + + + + True + False + _View + True + + + True + False + + + True + False + Opens the map view window. + Show _Map View + True + + + + + True + False + Opens the map toolbox window. + Show Map _Tools + True + + + + + True + False + Show Map _Properties + True + + + + + + + + + True + False + + + + + True + False + True + _Info + True + + + True + False + + + True + False + Opens a window with information about this program. + _About + True + + @@ -45,15 +346,12 @@ - - 65535 - 1 - 10 - False 5 Map Properties + win-main + win-main @@ -898,200 +1196,56 @@ 3 - - - - - False - True - dialog - Tycho Map Editor - By Alison Sanderson. Public domain. - greetigs i am tico the of superior ai to durdumbal go shoot my soldiers because its funny or ill put you in space - Home Page - To the extent possible under law, I, Alison Sanderson, have waived all -copyright and related or neighboring rights to this Document as described by -the Creative Commons Zero license as follows: - -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. - - image-loading - custom - - - - - - False - vertical - 2 - + + True False end + + + _Save + True + True + True + True + + + True + True + 0 + + + + + _Close + True + True + True + True + + + True + True + 1 + + False - False - 0 + True + 4 - - - - - - About Screen - The about screen for Tycho. - dialog - - - - - True - False - 24 - tycho-lines - - - True - False - 24 - tycho-points - - - True - False - 24 - tycho-polys False Tool Palette 250 True + win-main + win-main @@ -1186,142 +1340,34 @@ express Statement of Purpose. - + False - Tycho - False - 120 - 250 - + Map View + 600 + 400 + win-main + win-main + - + True - False - ttb + True + always + always + top-right + False - + True False - _File - True - - + adj-map-horz + adj-map-vert + + True False - - - True - False - Create a new project. - _New Project - True - - - - - True - False - Opens any type of project file. - _Open - True - - - - - True - False - Saves the currently open project. - _Save - True - - - - - True - False - - - - - True - False - Quit the application. - _Quit - True - - - - - - - - - True - False - _View - True - - - True - False - - - True - False - Opens the map view window. - Show _Map View - True - - - - - True - False - Opens the map toolbox window. - Show Map _Tools - True - - - - - True - False - Show Map _Properties - True - - - - - - - - - True - False - - - - - True - False - True - _Info - True - - - True - False - - - True - False - Opens a window with information about this program. - _About - True - - diff --git a/source/tycho/interfaces/editor.rs b/source/tycho/interfaces/editor.rs index acc298b..5dc22c5 100644 --- a/source/tycho/interfaces/editor.rs +++ b/source/tycho/interfaces/editor.rs @@ -3,151 +3,47 @@ use super::glib::*; use gobject_sys::*; use gtk_sys::*; -use maraiah::{durandal::ffi, marathon::map, rozinante::editor}; +use maraiah::{durandal::ffi, marathon::map}; +use std::cell::RefCell; -// Iterates over each flag widget with its respective ordered flag object. -fn each_flag(buttons: &[PropFlag], ordering: &[T], mut f: F) - where F: FnMut(&PropFlag, &T) +impl EditorModel { - for (flg, ord) in buttons.iter().zip(ordering) { - f(flg, ord); - } -} - -// Creates a closure which sets if a button is toggled. -fn r_flg(mut f: F) -> impl FnMut(&PropFlag, &T) - where F: FnMut(&T) -> bool -{ - move |flg, ord| { - unsafe { - // we have to block the signal handler so that it doesn't cause an - // infinite recursion of updating - g_signal_handler_block(*flg.w as _, flg.h); - - gtk_toggle_button_set_active(*flg.w, f(ord).into()); - - g_signal_handler_unblock(*flg.w as _, flg.h); - } - } -} - -// Creates a closure which checks if a button is toggled. -fn s_flg(mut f: F) -> impl FnMut(&PropFlag, &T) - where F: FnMut(&T, bool) -{ - move |flg, ord| f(ord, unsafe {gtk_toggle_button_get_active(*flg.w)} != 0) -} - -impl MapEditor -{ - /// Propagates all updated map information to widgets. - pub fn cause_refresh(&self) + pub fn new(view: EditorView) -> Self { - self.cause_refresh_view(); - self.cause_refresh_props(); + Self{view} } - /// Propagates updated map view information to widgets. - pub fn cause_refresh_view(&self) + pub fn open_new(&mut self) { - unsafe { - gtk_widget_queue_draw(*self.draw); - } + eprintln!("open_new"); } - /// Propagates updated map property information to widgets. - pub fn cause_refresh_props(&self) + pub fn open_buf(&mut self, b: &[u8]) { - let inf = &self.cur_block().info; - - each_flag(&self.fent, &O_ENT, r_flg(|&f| inf.entr_flags.contains(f))); - each_flag(&self.fenv, &O_ENV, r_flg(|&f| inf.envi_flags.contains(f))); - each_flag(&self.fmsn, &O_MSN, r_flg(|&f| inf.miss_flags.contains(f))); - } - - /// Propagates updated map property information to the editor state. - pub fn cause_update_props(&mut self) - { - let mut blk = self.cur_block().clone(); - let inf = &mut blk.info; - - each_flag(&self.fent, &O_ENT, s_flg(|&f, s| inf.entr_flags.set(f, s))); - each_flag(&self.fenv, &O_ENV, s_flg(|&f, s| inf.envi_flags.set(f, s))); - each_flag(&self.fmsn, &O_MSN, s_flg(|&f, s| inf.miss_flags.set(f, s))); - - self.push_block(blk); - self.cause_refresh_view(); + eprintln!("open_buf"); } } -impl std::ops::Deref for MapEditor +pub struct EditorPresenter { - type Target = editor::MapEditor; - - #[inline] - fn deref(&self) -> &Self::Target {&self.edit} } -impl std::ops::DerefMut for MapEditor +pub struct EditorView { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target {&mut self.edit} + pub prop: PropertiesWindow, } -/// Specialized map editor which has callbacks for frontend purposes. -pub struct MapEditor +pub struct PropertiesWindow { - pub edit: editor::MapEditor, - pub draw: Refc<'static, GtkWidget>, - pub fent: Vec, - pub fenv: Vec, - pub fmsn: Vec, + pub flg_ent: Vec>, + pub flg_env: Vec>, + pub flg_msn: Vec>, } -/// A runtime reference to the map editor. -pub type MapEditorRef = std::cell::RefCell; - -pub struct PropFlag +pub struct EditorModel { - pub w: Refc<'static, GtkToggleButton>, - pub h: ffi::c_ulong, } -// NOTE: this is flipped because of GTK weirdness. don't touch -const O_ENT: [map::minf::EntFlags; 8] = [ - map::minf::EntFlags::CTF, - map::minf::EntFlags::RUGBY, - map::minf::EntFlags::DEFENSE, - map::minf::EntFlags::KOTH, - map::minf::EntFlags::KTMWTB, - map::minf::EntFlags::CARNAGE, - map::minf::EntFlags::CO_OP, - map::minf::EntFlags::SOLO, -]; - -const O_ENV: [map::minf::EnvFlags; 11] = [ - map::minf::EnvFlags::VACUUM, - map::minf::EnvFlags::MAGNETIC, - map::minf::EnvFlags::REBELLION, - map::minf::EnvFlags::LOW_GRAV, - map::minf::EnvFlags::M1_GLUE, - map::minf::EnvFlags::LAVA_FLOOR, - map::minf::EnvFlags::REBELLION2, - map::minf::EnvFlags::MUSIC, - map::minf::EnvFlags::TERM_PAUSE, - map::minf::EnvFlags::M1_MONSTER, - map::minf::EnvFlags::M1_WEPS, -]; - -const O_MSN: [map::minf::MsnFlags; 8] = [ - map::minf::MsnFlags::EXTERMINATION, - map::minf::MsnFlags::EXPLORATION, - map::minf::MsnFlags::RETRIEVAL, - map::minf::MsnFlags::REPAIR, - map::minf::MsnFlags::RESCUE, - map::minf::MsnFlags::M1_EXPLORATION, - map::minf::MsnFlags::M1_RESCUE, - map::minf::MsnFlags::M1_REPAIR, -]; +pub type EditorRef = std::cell::RefCell; // EOF diff --git a/source/tycho/main.rs b/source/tycho/main.rs index 254d270..b06c140 100644 --- a/source/tycho/main.rs +++ b/source/tycho/main.rs @@ -7,66 +7,38 @@ use gio_sys::*; use glib_sys::*; use gobject_sys::*; use gtk_sys::*; -use maraiah::{c_str, durandal::ffi}; +use maraiah::{c_str, + durandal::{err::*, ffi}}; use std::{cell::RefCell, rc::Rc}; -const APP_ID: ffi::NT = c_str!("net.greyserv.maraiah.tycho"); -const B_ADJ_M_HORZ: ffi::NT = c_str!("adj-map-horz"); -const B_ADJ_M_VERT: ffi::NT = c_str!("adj-map-vert"); -const B_BTN_ABOUT: ffi::NT = c_str!("btn-about"); -const B_BTN_M_PROP: ffi::NT = c_str!("btn-show-map-prop"); -const B_BTN_M_TOOL: ffi::NT = c_str!("btn-show-map-tools"); -const B_BTN_M_VIEW: ffi::NT = c_str!("btn-show-map-view"); -const B_BTN_NEW: ffi::NT = c_str!("btn-new"); -const B_BTN_OPEN: ffi::NT = c_str!("btn-open"); -const B_BTN_QUIT: ffi::NT = c_str!("btn-quit"); -const B_CON_F_ENT: ffi::NT = c_str!("con-f-ent"); -const B_CON_F_ENV: ffi::NT = c_str!("con-f-env"); -const B_CON_F_MSN: ffi::NT = c_str!("con-f-msn"); -const B_DLG_ABOUT: ffi::NT = c_str!("dlg-about"); -const B_DRAW_AREA: ffi::NT = c_str!("draw-area"); -const B_WIN_MAIN: ffi::NT = c_str!("win-main"); -const B_WIN_M_PROP: ffi::NT = c_str!("win-map-prop"); -const B_WIN_M_TOOL: ffi::NT = c_str!("win-map-tools"); -const B_WIN_M_VIEW: ffi::NT = c_str!("win-map-view"); -const E_ACTIVATE: ffi::NT = c_str!("activate"); -const E_DELETE: ffi::NT = c_str!("delete-event"); -const E_DESTROY: ffi::NT = c_str!("destroy"); -const E_DRAW: ffi::NT = c_str!("draw"); -const E_SHUTDOWN: ffi::NT = c_str!("shutdown"); -const E_TOGGLE: ffi::NT = c_str!("toggled"); -const IM_ABOUT: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/tycho2.png"); -const IM_NOMAP: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/tycho1.png"); -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, _: gpointer) { // Callback to finalize the reference. unsafe extern "C" fn c_done(_: *mut GApplication, ptr: gpointer) { - let edit = Rc::from_raw(ptr as *const MapEditorRef); + let edit = Rc::from_raw(ptr as *const EditorRef); 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, B_DRAW_AREA)), - fent: get_flag_fields(&b, B_CON_F_ENT), - fenv: get_flag_fields(&b, B_CON_F_ENV), - fmsn: get_flag_fields(&b, B_CON_F_MSN)}; + let prop = PropertiesWindow{flg_ent: get_flag_fields(&b, B_CON_F_ENT), + flg_env: get_flag_fields(&b, B_CON_F_ENV), + flg_msn: get_flag_fields(&b, B_CON_F_MSN)}; + let edit = EditorModel::new(EditorView{prop}); let edit = RefCell::new(edit); let edit = Rc::new(edit); setup_css(); - setup_toggles(edit.clone()); - setup_draw_area(&b, edit.clone()); - setup_win_map_view(&b); - setup_win_map_tools(&b); - setup_win_map_prop(&b); + //setup_draw_area(&b, edit.clone()); + let wv = setup_win(&b, B_WIN_M_VIEW, B_BTN_M_VIEW); + let wt = setup_win(&b, B_WIN_M_TOOL, B_BTN_M_TOOL); + let _ = setup_win(&b, B_WIN_M_PROP, B_BTN_M_PROP); + gtk_widget_show_all(wv); + gtk_widget_show_all(wt); + setup_about_dlg(&b); setup_win_main(&b, app, edit.clone()); @@ -74,7 +46,8 @@ unsafe extern "C" fn app_activate(app: *mut GtkApplication, _: gpointer) } // Gets all of the toggle buttons from a container. -unsafe fn get_flag_fields(b: &Refc, name: ffi::NT) -> Vec +unsafe fn get_flag_fields(b: &Refc, name: ffi::NT) + -> Vec> { let mut flags = Vec::new(); @@ -82,127 +55,28 @@ unsafe fn get_flag_fields(b: &Refc, name: ffi::NT) -> Vec let head = ListD::new(gtk_container_get_children(head)); let gtyp = gtk_toggle_button_get_type(); - get_typed_from(head, gtyp, |obj| { - flags.push(PropFlag{w: Refc::own(obj as _), h: 0}); - }); + get_typed_from(head, gtyp, |obj| flags.push(Refc::own(obj as _))); flags } -// Connects toggle events to every flag in the map properties window. -unsafe fn setup_toggles(edit: Rc) -{ - let mut ed = edit.borrow_mut(); - - connect_toggle(edit.clone(), ed.fent.iter_mut()); - connect_toggle(edit.clone(), ed.fenv.iter_mut()); - connect_toggle(edit.clone(), ed.fmsn.iter_mut()); -} - -// Connects toggle events to each of the widgets in `it`. -unsafe fn connect_toggle<'a, I>(edit: Rc, it: I) - where I: Iterator -{ - // Callback for when the button is toggled, which causates an update. - unsafe extern "C" fn c_toggled(_: *mut GtkToggleButton, edit: gpointer) - { - let edit = &*(edit as *const MapEditorRef); - edit.borrow_mut().cause_update_props(); - } - - // go over each widget, set its object and callback handle - for flg in it { - let erf = connect_ref(*flg.w, edit.clone()); - flg.h = connect(*flg.w, E_TOGGLE, c_toggled as _, erf); - } -} - -// Sets up the map view window's drawing area. -unsafe fn setup_draw_area(b: &Refc, edit: Rc) -{ - // All of the state necessary for the drawing area. - struct RenderState - { - im_nomap: Refc<'static, GdkPixbuf>, - ax: Refc<'static, GtkAdjustment>, - ay: Refc<'static, GtkAdjustment>, - edit: Rc, - } - - // Callback to finalize the drawing area. - unsafe extern "C" fn c_done(_: *mut GtkWidget, rend: gpointer) - { - Box::from_raw(rend as *mut RenderState); - } - - // Callback to draw on the drawing area. - unsafe extern "C" fn c_draw(wid: *mut GtkWidget, - ctx: *mut cairo_sys::cairo_t, - rend: gpointer) - -> gboolean - { - let rend = &mut *(rend as *mut RenderState); - - 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.ay, 0.0); - gtk_adjustment_set_upper(*rend.ay, h); - - let im = CrImage(*rend.im_nomap); - let mut dr = CrDrawArea::new(ctx, w, h); - - rend.edit.borrow().draw(&mut dr, &im); - - 1 - } - - let wid = get_obj::(b, B_DRAW_AREA); - - // get all of the necessary state and related objects - let ax = Refc::own(get_obj(b, B_ADJ_M_HORZ)); - let ay = Refc::own(get_obj(b, B_ADJ_M_VERT)); - - let im_nomap = Refc::new(load_img(IM_NOMAP)); - - let rend = RenderState{im_nomap, ax, ay, edit}; - let rend = Box::into_raw(Box::new(rend)); - - connect(wid, E_DESTROY, c_done as _, rend); - connect(wid, E_DRAW, c_draw as _, rend); -} - // Sets up the map view window. -unsafe fn setup_win_map_view(b: &Refc) +unsafe fn setup_win(b: &Refc, win: ffi::NT, btn: ffi::NT) + -> *mut GtkWidget { - let win = get_obj::(b, B_WIN_M_VIEW); - let btn = get_obj::(b, B_BTN_M_VIEW); + // Callback to show the widget. + unsafe extern "C" fn c_show_act(_: *mut GtkWidget, wid: gpointer) + { + gtk_widget_show_all(wid as _); + } + + let win = get_obj::(b, win); + let btn = get_obj::(b, btn); connect_hide(win); - connect_show(btn, win); -} + connect(btn, E_ACTIVATE, c_show_act as _, win); -// Sets up the map tools window. -unsafe fn setup_win_map_tools(b: &Refc) -{ - let win = get_obj::(b, B_WIN_M_TOOL); - let btn = get_obj::(b, B_BTN_M_TOOL); - - connect_hide(win); - connect_show(btn, win); -} - -// Sets up the map properties window. -unsafe fn setup_win_map_prop(b: &Refc) -{ - let win = get_obj::(b, B_WIN_M_PROP); - let btn = get_obj::(b, B_BTN_M_PROP); - - connect_hide(win); - connect_show(btn, win); + win as *mut GtkWidget } // Sets up the about dialogue. @@ -284,7 +158,7 @@ unsafe fn get_typed_from(it: I, ty: GType, mut f: F) // Sets up the main menu window. unsafe fn setup_win_main(b: &Refc, 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) @@ -295,45 +169,30 @@ unsafe fn setup_win_main(b: &Refc, // Callback to create a new map when the "New" button is pressed. unsafe extern "C" fn c_new_act(_: *mut GtkWidget, edit: gpointer) { - let edit = &*(edit as *const MapEditorRef); - let mut edit = edit.borrow_mut(); + let edit = &*(edit as *const EditorRef); - if edit.unclean() { - let titl = c_str!("Confirm"); - let text = c_str!("Are you sure you want to create a new project? \ - Unsaved data may be lost."); + edit.borrow_mut().open_new(); + } - if !run_ok_cancel_dlg(titl, text) { - return; - } - } + // Opens the map editor with a buffer. + unsafe fn open_buf(path: &str, edit: &mut EditorModel) -> ResultS<()> + { + let fp = std::fs::File::open(&path)?; + let mm = memmap::Mmap::map(&fp)?; - edit.open_new(); - edit.cause_refresh(); + edit.open_buf(&mm); + + Ok(()) } // Callback to open an existing map when the "Open" button is pressed. unsafe extern "C" fn c_open_act(_: *mut GtkWidget, edit: gpointer) { - let edit = &*(edit as *const MapEditorRef); - let mut edit = edit.borrow_mut(); - - if edit.unclean() { - let titl = c_str!("Confirm"); - let text = c_str!("Are you sure you want to open this project? \ - Unsaved data may be lost."); - - if !run_ok_cancel_dlg(titl, text) { - return; - } - } + let edit = &*(edit as *const EditorRef); if let Some(path) = run_file_chooser_open() { // TODO: handle errors gracefully - let fp = std::fs::File::open(&path).unwrap(); - let mm = memmap::Mmap::map(&fp).unwrap(); - edit.open_buf(&mm); - edit.cause_refresh(); + open_buf(&path, &mut edit.borrow_mut()).unwrap(); } } @@ -367,32 +226,6 @@ unsafe fn setup_css() gtk_style_context_add_provider_for_screen(scr, *css as _, pri); } -// Runs a modal OK/Cancel dialogue. -unsafe fn run_ok_cancel_dlg(title: ffi::NT, text: ffi::NT) -> bool -{ - let flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; - let dlg = gtk_dialog_new_with_buttons(title, - ffi::null_mut(), - flags, - c_str!("_OK"), - GTK_RESPONSE_ACCEPT, - c_str!("_Cancel"), - GTK_RESPONSE_REJECT, - ffi::null_mut_void()); - - let area = gtk_dialog_get_content_area(dlg as _); - let labl = gtk_label_new(text); - - gtk_container_add(area as _, labl); - gtk_widget_show_all(area as _); - - let res = gtk_dialog_run(dlg as _); - - gtk_widget_destroy(dlg); - - res == GTK_RESPONSE_ACCEPT -} - // Runs a modal Open File dialogue. unsafe fn run_file_chooser_open() -> Option { @@ -440,26 +273,13 @@ unsafe fn connect_hide(wid: *mut T) connect(wid, E_DELETE, c_hide_del as _, ffi::null_void()); } -// Connects a handler that shows a widget when activated. -unsafe fn connect_show(btn: *mut T, wid: *mut U) -{ - // Callback to show the widget. - unsafe extern "C" fn c_show_act(_: *mut GtkWidget, wid: gpointer) - { - gtk_widget_show_all(wid as _); - } - - connect(btn, E_ACTIVATE, c_show_act as _, wid); -} - // Connects the map editor reference to a widget. -unsafe fn connect_ref(obj: *mut T, rc: Rc) - -> *const MapEditorRef +unsafe fn connect_ref(obj: *mut T, rc: Rc) -> *const EditorRef { // Callback to finalize the reference. unsafe extern "C" fn c_done(_: *mut GtkWidget, ptr: gpointer) { - Rc::from_raw(ptr as *const MapEditorRef); + Rc::from_raw(ptr as *const EditorRef); } let ptr = Rc::into_raw(rc); @@ -521,4 +341,34 @@ fn main() } } +const APP_ID: ffi::NT = c_str!("net.greyserv.maraiah.tycho"); +const B_ADJ_M_HORZ: ffi::NT = c_str!("adj-map-horz"); +const B_ADJ_M_VERT: ffi::NT = c_str!("adj-map-vert"); +const B_BTN_ABOUT: ffi::NT = c_str!("btn-about"); +const B_BTN_M_PROP: ffi::NT = c_str!("btn-show-map-prop"); +const B_BTN_M_TOOL: ffi::NT = c_str!("btn-show-map-tools"); +const B_BTN_M_VIEW: ffi::NT = c_str!("btn-show-map-view"); +const B_BTN_NEW: ffi::NT = c_str!("btn-new"); +const B_BTN_OPEN: ffi::NT = c_str!("btn-open"); +const B_BTN_QUIT: ffi::NT = c_str!("btn-quit"); +const B_CON_F_ENT: ffi::NT = c_str!("con-f-ent"); +const B_CON_F_ENV: ffi::NT = c_str!("con-f-env"); +const B_CON_F_MSN: ffi::NT = c_str!("con-f-msn"); +const B_DLG_ABOUT: ffi::NT = c_str!("dlg-about"); +const B_DRAW_AREA: ffi::NT = c_str!("draw-area"); +const B_WIN_MAIN: ffi::NT = c_str!("win-main"); +const B_WIN_M_PROP: ffi::NT = c_str!("win-map-prop"); +const B_WIN_M_TOOL: ffi::NT = c_str!("win-map-tools"); +const B_WIN_M_VIEW: ffi::NT = c_str!("win-map-view"); +const E_ACTIVATE: ffi::NT = c_str!("activate"); +const E_DELETE: ffi::NT = c_str!("delete-event"); +const E_DESTROY: ffi::NT = c_str!("destroy"); +const E_DRAW: ffi::NT = c_str!("draw"); +const E_SHUTDOWN: ffi::NT = c_str!("shutdown"); +const E_TOGGLE: ffi::NT = c_str!("toggled"); +const IM_ABOUT: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/tycho2.png"); +const IM_NOMAP: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/tycho1.png"); +const PATH_BUILDER: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/ui"); +const PATH_CSS: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/css"); + // EOF