diff --git a/Cargo.lock b/Cargo.lock index 9a3af60..6c24e3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -67,6 +76,7 @@ dependencies = [ "image", "serde", "serde_json", + "state", "zip", ] @@ -328,6 +338,19 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +[[package]] +name = "generator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "winapi", +] + [[package]] name = "generic-array" version = "0.14.5" @@ -484,6 +507,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "loom" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -571,6 +618,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -626,6 +679,12 @@ dependencies = [ "syn", ] +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + [[package]] name = "pkg-config" version = "0.3.25" @@ -692,12 +751,48 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "regex" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -763,6 +858,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "smallvec" version = "1.8.0" @@ -778,6 +882,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "state" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] + [[package]] name = "subtle" version = "2.4.1" @@ -795,6 +908,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + [[package]] name = "threadpool" version = "1.8.1" @@ -833,6 +955,68 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +[[package]] +name = "tracing" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +dependencies = [ + "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "ttf-parser" version = "0.15.0" @@ -851,6 +1035,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" @@ -923,6 +1113,28 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "zip" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index 7b9c7f3..c285a1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] fltk = "1.3.6" +state = "0.5.3" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.79" zip = "0.6.2" diff --git a/board.zip b/board.zip index a7533b3..bc4d9b8 100644 Binary files a/board.zip and b/board.zip differ diff --git a/src/main.rs b/src/main.rs index 31e5dae..801af48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,14 +9,18 @@ extern crate image; use image::io::Reader as ImageReader; use image::{ DynamicImage }; +use state::Storage; + use std::collections::{HashMap, HashSet}; -use std::cell::RefCell; -use std::rc::Rc; +use std::sync::Mutex; use std::io::{ Write, Read, Cursor }; use std::fs::File; +//////////////////// Global State //////////////////// +// Don't @ me... +static STATE: Storage> = Storage::new(); //////////////////// Data Layout //////////////////// @@ -131,14 +135,16 @@ fn node_create_dialog(state: &mut AppState, pos_x: f32, pos_y: f32) { mod dispatch { use super::*; type Coords = (f32, f32); - pub(super) fn node_press(state: &mut AppState, coords: Coords) { + pub(super) fn node_press(coords: Coords) { let (pos_x, pos_y) = coords; if app::event_button() == 1 { let name = dialog::input_default("Node", ""); if let Some(name) = name { + let mut state = STATE.get().lock().unwrap(); state.board.add_node(pos_x, pos_y, name); } } else if app::event_button() == 3 { + let mut state = STATE.get().lock().unwrap(); let id = state.board.nearest_node(pos_x, pos_y); if let Some(id) = id { state.board.remove_node(id); @@ -146,8 +152,9 @@ mod dispatch { } app::redraw(); } - pub(super) fn edge_press(state: &mut AppState, coords: Coords) { + pub(super) fn edge_press(coords: Coords) { let (pos_x, pos_y) = coords; + let mut state = STATE.get().lock().unwrap(); if app::event_button() == 1 { match (state.selected_node, state.board.nearest_node(pos_x, pos_y)) { (Some(selected), Some(nearest)) => { @@ -218,7 +225,7 @@ impl CoordTransformer for frame::Frame { } //////////////////// App State //////////////////// - +#[derive(Clone, Copy)] enum EditMode { Node, Edge, @@ -245,6 +252,8 @@ impl AppState { //////////////////// Procedural App Creation //////////////////// fn main() { + // State + STATE.set(Mutex::new(AppState::new())); // App setup let app = app::App::default() .with_scheme(app::Scheme::Gtk); @@ -255,17 +264,12 @@ fn main() { .size_of_parent(); flex.set_type(group::FlexType::Column); - // State - let state = Rc::new(RefCell::new(AppState::new())); - // Menu let mut menubar = menu::MenuBar::default(); - let state_clone = Rc::clone(&state); menubar.add("File/New", Shortcut::None, menu::MenuFlag::Normal, move |_| { - state_clone.replace(AppState::new()); + *STATE.get().lock().unwrap() = AppState::new(); app::redraw(); }); - let state_clone = Rc::clone(&state); menubar.add("File/Open...", Shortcut::None, menu::MenuFlag::Normal, move |_| { let mut fc = dialog::NativeFileChooser::new(dialog::NativeFileChooserType::BrowseFile); fc.show(); @@ -285,9 +289,8 @@ fn main() { state.image_raw = Some(image); app::redraw(); } - state_clone.replace(state); + *STATE.get().lock().unwrap() = state; }); - let state_clone = Rc::clone(&state); menubar.add("File/Open Image...", Shortcut::None, menu::MenuFlag::Normal, move |_| { let mut fc = dialog::NativeFileChooser::new(dialog::NativeFileChooserType::BrowseFile); fc.show(); @@ -295,7 +298,7 @@ fn main() { match ImageReader::open(filename).map(|i| i.decode()) { Ok(Ok(image)) => { - let mut state = state_clone.borrow_mut(); + let mut state = STATE.get().lock().unwrap(); let data = encode_png(&image); state.image = Some(PngImage::from_data(&data).unwrap()); state.image_raw = Some(image); @@ -304,7 +307,6 @@ fn main() { _ => dialog::alert_default("Error opening file"), } }); - let state_clone = Rc::clone(&state); menubar.add("File/Save As ...", Shortcut::None, menu::MenuFlag::Normal, move |_| { let mut fc = dialog::NativeFileChooser::new(dialog::NativeFileChooserType::BrowseSaveFile); fc.show(); @@ -312,7 +314,7 @@ fn main() { let file = File::create(fc.filename()).unwrap(); let mut ar = zip::ZipWriter::new(file); let options = zip::write::FileOptions::default(); - let state = state_clone.borrow(); + let mut state = STATE.get().lock().unwrap(); ar.start_file("graph.json", options).ok(); ar.write(&serde_json::to_vec(&state.board).unwrap()).ok(); @@ -324,14 +326,12 @@ fn main() { } ar.finish().ok(); }); - let state_clone = Rc::clone(&state); menubar.add("Edit/Edit Nodes", Shortcut::None, menu::MenuFlag::Normal, move |_| { - let mut state = state_clone.borrow_mut(); + let mut state = STATE.get().lock().unwrap(); state.edit_mode = EditMode::Node; }); - let state_clone = Rc::clone(&state); menubar.add("Edit/Edit Edges", Shortcut::None, menu::MenuFlag::Normal, move |_| { - let mut state = state_clone.borrow_mut(); + let mut state = STATE.get().lock().unwrap(); state.edit_mode = EditMode::Edge; }); @@ -339,10 +339,9 @@ fn main() { // Canvas let mut frame = frame::Frame::default(); - let state_clone = Rc::clone(&state); frame.draw(move |f| { use draw::*; - let mut state = state_clone.borrow_mut(); + let mut state = STATE.get().lock().unwrap(); // Background let image = &mut state.image; if let Some(image) = image.as_mut() { @@ -369,16 +368,15 @@ fn main() { } } }); - let state_clone = Rc::clone(&state); frame.handle(move |f, e| { match e { Event::Push => { - let mut state = state_clone.borrow_mut(); + let edit_mode = STATE.get().lock().unwrap().edit_mode; let coords = f.to_coords(app::event_x(), app::event_y()); - match state.edit_mode { - EditMode::Node => dispatch::node_press(&mut state, coords), - EditMode::Edge => dispatch::edge_press(&mut state, coords), + match edit_mode { + EditMode::Node => dispatch::node_press(coords), + EditMode::Edge => dispatch::edge_press(coords), } true }