Can turn on a "horizontal wrap" setting
This commit is contained in:
parent
6ded5cacbc
commit
67ff5dd0df
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -146,7 +146,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "board-builder-gui"
|
name = "board-builder-gui"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"board-builder",
|
"board-builder",
|
||||||
"eframe",
|
"eframe",
|
||||||
|
@ -3,10 +3,9 @@ name = "board-builder-gui"
|
|||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
board-builder = { path = "../" }
|
board-builder = { path = "../" }
|
||||||
eframe = "0.18.0"
|
eframe = "0.18.0"
|
||||||
rfd = "0.8.2"
|
rfd = "0.8.2"
|
||||||
image = "0.24.2"
|
image = "0.24.2"
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use image::DynamicImage;
|
|||||||
|
|
||||||
use rfd::FileDialog;
|
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::path::Path;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@ -29,6 +29,7 @@ struct BoardBuilderApp {
|
|||||||
create_node_dialog: CreateNodeDialog,
|
create_node_dialog: CreateNodeDialog,
|
||||||
edit_node_dialog: EditNodeDialog,
|
edit_node_dialog: EditNodeDialog,
|
||||||
edit_labels_dialog: EditLabelsDialog,
|
edit_labels_dialog: EditLabelsDialog,
|
||||||
|
edit_settings_dialog: EditSettingsDialog,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -93,7 +94,10 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
if ui.button("Edit Labels...").clicked() {
|
if ui.button("Edit Labels...").clicked() {
|
||||||
self.edit_labels_dialog.show(Rc::clone(&self.board));
|
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| {
|
CentralPanel::default().show(ctx, |ui| {
|
||||||
@ -121,6 +125,7 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
self.create_node_dialog.ui(ctx);
|
self.create_node_dialog.ui(ctx);
|
||||||
self.edit_node_dialog.ui(ctx);
|
self.edit_node_dialog.ui(ctx);
|
||||||
self.edit_labels_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 };
|
let stroke = Stroke { width: 1.0, color: Color32::BLACK };
|
||||||
for edge in &node.edges {
|
for edge in &node.edges {
|
||||||
let other_node = &board.nodes[edge];
|
let other_node = &board.nodes[edge];
|
||||||
painter.line_segment(
|
if board.config.horizontal_wrapping && should_wrap_horizontal(node, other_node) {
|
||||||
[view.inv_xform(node.x, node.y), view.inv_xform(other_node.x, other_node.y)],
|
let mut nodes = [node, other_node];
|
||||||
stroke,
|
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)]
|
#[derive(Default)]
|
||||||
struct StringDialog {
|
struct StringDialog {
|
||||||
string: String,
|
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<RefCell<Board>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EditSettingsDialog {
|
||||||
|
fn show(&mut self, board: Rc<RefCell<Board>>) {
|
||||||
|
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");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Binary file not shown.
29
src/lib.rs
29
src/lib.rs
@ -1,6 +1,18 @@
|
|||||||
use serde::{ Serialize, Deserialize };
|
use serde::{ Serialize, Deserialize };
|
||||||
use std::collections::{ HashMap, HashSet };
|
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)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Node {
|
pub struct Node {
|
||||||
@ -16,14 +28,9 @@ pub struct Node {
|
|||||||
pub struct Board {
|
pub struct Board {
|
||||||
pub labels: HashMap<String, HashSet<String>>,
|
pub labels: HashMap<String, HashSet<String>>,
|
||||||
pub nodes: HashMap<usize, Node>,
|
pub nodes: HashMap<usize, Node>,
|
||||||
|
pub config: Config,
|
||||||
}
|
}
|
||||||
impl Board {
|
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) {
|
pub fn add_node(&mut self, x: f32, y: f32, name: String) {
|
||||||
self.nodes.insert(self.next_id(), Node {
|
self.nodes.insert(self.next_id(), Node {
|
||||||
x,
|
x,
|
||||||
@ -60,8 +67,8 @@ impl Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_edge(&mut self, from: usize, to: usize) {
|
pub fn add_edge(&mut self, from: usize, to: usize) {
|
||||||
let node = self.nodes.get_mut(&from).expect("Could not find node");
|
let node = self.nodes.get_mut(&from).expect("Could not find node");
|
||||||
node.edges.insert(to);
|
node.edges.insert(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nearest_node(&self, x: f32, y: f32) -> Option<usize> {
|
pub fn nearest_node(&self, x: f32, y: f32) -> Option<usize> {
|
||||||
@ -97,6 +104,12 @@ fn dist_sq((x0, y0): (f32, f32), (x1, y1): (f32, f32)) -> f32 {
|
|||||||
(x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)
|
(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;
|
||||||
use std::io::{ Write, Read, Cursor };
|
use std::io::{ Write, Read, Cursor };
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
Loading…
Reference in New Issue
Block a user