From 67ff5dd0df2af6a2ad1c96a648af4d063d5828ad Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Tue, 7 Jun 2022 16:46:02 -0500 Subject: [PATCH] Can turn on a "horizontal wrap" setting --- Cargo.lock | 2 +- board-builder-gui/Cargo.toml | 5 ++- board-builder-gui/src/main.rs | 56 +++++++++++++++++++++++++++++----- samples/risk.board | Bin 512810 -> 512846 bytes src/lib.rs | 29 +++++++++++++----- 5 files changed, 73 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8a5785..ef25d7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,7 +146,7 @@ dependencies = [ [[package]] name = "board-builder-gui" -version = "1.0.0" +version = "1.1.0" dependencies = [ "board-builder", "eframe", diff --git a/board-builder-gui/Cargo.toml b/board-builder-gui/Cargo.toml index 7b4cab9..c49b81b 100644 --- a/board-builder-gui/Cargo.toml +++ b/board-builder-gui/Cargo.toml @@ -3,10 +3,9 @@ name = "board-builder-gui" version = "1.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] board-builder = { path = "../" } eframe = "0.18.0" rfd = "0.8.2" -image = "0.24.2" \ No newline at end of file +image = "0.24.2" + diff --git a/board-builder-gui/src/main.rs b/board-builder-gui/src/main.rs index 07b7aee..fbbae6e 100644 --- a/board-builder-gui/src/main.rs +++ b/board-builder-gui/src/main.rs @@ -7,7 +7,7 @@ use image::DynamicImage; use rfd::FileDialog; -use board_builder::{ Board, Node, CoordTransformer, read_board_from_file, write_board_to_file }; +use board_builder::{ Board, Node, CoordTransformer, read_board_from_file, write_board_to_file, should_wrap_horizontal }; use std::path::Path; use std::collections::HashSet; @@ -29,6 +29,7 @@ struct BoardBuilderApp { create_node_dialog: CreateNodeDialog, edit_node_dialog: EditNodeDialog, edit_labels_dialog: EditLabelsDialog, + edit_settings_dialog: EditSettingsDialog, } #[derive(Clone, Copy)] @@ -93,7 +94,10 @@ impl eframe::App for BoardBuilderApp { if ui.button("Edit Labels...").clicked() { self.edit_labels_dialog.show(Rc::clone(&self.board)); } - }) + }); + if ui.button("Settings...").clicked() { + self.edit_settings_dialog.show(Rc::clone(&self.board)); + }; }); }); CentralPanel::default().show(ctx, |ui| { @@ -121,6 +125,7 @@ impl eframe::App for BoardBuilderApp { self.create_node_dialog.ui(ctx); self.edit_node_dialog.ui(ctx); self.edit_labels_dialog.ui(ctx); + self.edit_settings_dialog.ui(ctx); } } @@ -169,10 +174,25 @@ impl BoardBuilderApp { let stroke = Stroke { width: 1.0, color: Color32::BLACK }; for edge in &node.edges { let other_node = &board.nodes[edge]; - painter.line_segment( - [view.inv_xform(node.x, node.y), view.inv_xform(other_node.x, other_node.y)], - stroke, - ); + if board.config.horizontal_wrapping && should_wrap_horizontal(node, other_node) { + let mut nodes = [node, other_node]; + nodes.sort_by(|a, b| a.x.partial_cmp(&b.x).unwrap()); + let [left_node, right_node] = nodes; + let y_mid = (left_node.y + right_node.y) / 2.0; + painter.line_segment( + [view.inv_xform(0.0, y_mid), view.inv_xform(left_node.x, left_node.y)], + stroke + ); + painter.line_segment( + [view.inv_xform(right_node.x, right_node.y), view.inv_xform(1.0, y_mid)], + stroke + ); + } else { + painter.line_segment( + [view.inv_xform(node.x, node.y), view.inv_xform(other_node.x, other_node.y)], + stroke, + ); + } } } } @@ -364,7 +384,6 @@ impl EditLabelsDialog { } } - #[derive(Default)] struct StringDialog { string: String, @@ -422,3 +441,26 @@ fn node_common_ui(ui: &mut Ui, node: &mut Node, board: &Board) { }); } } + +#[derive(Default)] +struct EditSettingsDialog { + open: bool, + board: Rc> +} + +impl EditSettingsDialog { + fn show(&mut self, board: Rc>) { + self.board = board; + self.open = true; + } + + fn ui(&mut self, ctx: &Context) { + Window::new("Settings") + .collapsible(false) + .open(&mut self.open) + .show(ctx, |ui| { + let mut board = self.board.borrow_mut(); + ui.checkbox(&mut board.config.horizontal_wrapping, "Horizontal Wrapping"); + }); + } +} diff --git a/samples/risk.board b/samples/risk.board index b3adf8fc5cccba4a40f9fe07006ebe615454fb7a..3832c0931c86ca0b98b682efd5a02fbf25e82c52 100644 GIT binary patch delta 1395 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 U2O9$A1eYz-2O9>Z(gy$l0Q)zPL;wH) diff --git a/src/lib.rs b/src/lib.rs index 9442bcf..cc314e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,18 @@ use serde::{ Serialize, Deserialize }; use std::collections::{ HashMap, HashSet }; +#[derive(Serialize, Deserialize, Debug)] +#[serde(default)] +pub struct Config { + pub horizontal_wrapping: bool, +} +impl Default for Config { + fn default() -> Self { + Config { + horizontal_wrapping: false, + } + } +} #[derive(Serialize, Deserialize, Debug, Default, Clone)] #[serde(default)] pub struct Node { @@ -16,14 +28,9 @@ pub struct Node { pub struct Board { pub labels: HashMap>, pub nodes: HashMap, + pub config: Config, } impl Board { - pub fn new() -> Self { - let nodes = HashMap::new(); - let labels = HashMap::new(); - Board { nodes, labels } - } - pub fn add_node(&mut self, x: f32, y: f32, name: String) { self.nodes.insert(self.next_id(), Node { x, @@ -60,8 +67,8 @@ impl Board { } pub fn add_edge(&mut self, from: usize, to: usize) { - let node = self.nodes.get_mut(&from).expect("Could not find node"); - node.edges.insert(to); + let node = self.nodes.get_mut(&from).expect("Could not find node"); + node.edges.insert(to); } pub fn nearest_node(&self, x: f32, y: f32) -> Option { @@ -97,6 +104,12 @@ fn dist_sq((x0, y0): (f32, f32), (x1, y1): (f32, f32)) -> f32 { (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) } +pub fn should_wrap_horizontal(node1: &Node, node2: &Node) -> bool { + let mut xs = [node1.x, node2.x]; + xs.sort_by(|a, b| a.partial_cmp(b).unwrap()); + xs[0] + (1.0 - xs[1]) < xs[1] - xs[0] +} + use std::io; use std::io::{ Write, Read, Cursor }; use std::fs::File;