From 1eeb59a4ac9fdb74534a51b9f7c390f332abfd7f Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Wed, 11 May 2022 15:17:12 -0500 Subject: [PATCH] Can add a label key --- board-builder-impl-egui/src/main.rs | 169 +++++++++++++++++++++++++--- 1 file changed, 156 insertions(+), 13 deletions(-) diff --git a/board-builder-impl-egui/src/main.rs b/board-builder-impl-egui/src/main.rs index c331835..42d7640 100644 --- a/board-builder-impl-egui/src/main.rs +++ b/board-builder-impl-egui/src/main.rs @@ -8,6 +8,9 @@ use rfd::FileDialog; use board_builder::{ Board, CoordTransformer, read_board_from_file, write_board_to_file }; use std::path::Path; +use std::collections::HashMap; +use std::rc::Rc; +use std::cell::RefCell; fn main() { let native_options = eframe::NativeOptions::default(); @@ -16,12 +19,13 @@ fn main() { #[derive(Default)] struct BoardBuilderApp { - board: Board, + board: Rc>, texture: Option, image: Option, edit_mode: EditMode, - create_node_dialog: CreateNodeDialog, selected_node: Option, + create_node_dialog: CreateNodeDialog, + edit_labels_dialog: EditLabelsDialog, } #[derive(Clone, Copy)] @@ -41,16 +45,17 @@ impl eframe::App for BoardBuilderApp { menu::bar(ui, |ui| { ui.menu_button("File", |ui| { if ui.button("New").clicked() { - self.board = Board::default(); + self.board.replace(Board::default()); self.texture = None; self.image = None; self.edit_mode = EditMode::Nodes; + ui.close_menu(); } if ui.button("Open...").clicked() { if let Some(board_file) = FileDialog::new().pick_file() { match read_board_from_file(&board_file) { Ok((board, image)) => { - self.board = board; + self.board.replace(board); match image { None => { self.image = None; self.texture = None } Some(image) => self.load_image(ctx, image), @@ -59,10 +64,11 @@ impl eframe::App for BoardBuilderApp { Err(_) => panic!("Could not open file!"), } } + ui.close_menu(); } if ui.button("Save As...").clicked() { if let Some(board_file) = FileDialog::new().save_file() { - write_board_to_file(&self.board, self.image.as_ref(), &board_file).expect("Something went wrong saving!"); + write_board_to_file(&self.board.borrow(), self.image.as_ref(), &board_file).expect("Something went wrong saving!"); } } if ui.button("Open Image...").clicked() { @@ -82,7 +88,7 @@ impl eframe::App for BoardBuilderApp { self.edit_mode = EditMode::Edges; } if ui.button("Edit Labels...").clicked() { - todo!(); + self.edit_labels_dialog.show(Rc::clone(&self.board)); } }) }); @@ -112,11 +118,12 @@ impl eframe::App for BoardBuilderApp { Window::new("Create Node") .collapsible(false) .show(ctx, |ui| { + let mut board = self.board.borrow_mut(); ui.label("Name:"); ui.text_edit_singleline(&mut self.create_node_dialog.name); if ui.button("Add").clicked() { self.create_node_dialog.close(); - self.board.add_node( + board.add_node( self.create_node_dialog.x, self.create_node_dialog.y, self.create_node_dialog.name.clone(), @@ -124,6 +131,9 @@ impl eframe::App for BoardBuilderApp { } }); } + if self.edit_labels_dialog.open { + self.draw_edit_labels_dialog(ctx); + } } } @@ -140,6 +150,7 @@ impl BoardBuilderApp { fn load_image_file(&mut self, ctx: &Context, image_file: &Path) -> Result<(), image::ImageError> { let image = image::io::Reader::open(image_file)?.decode()?; self.load_image(ctx, image); + Ok(()) } @@ -154,7 +165,8 @@ impl BoardBuilderApp { } fn draw_board(&self, painter: &Painter, view: View) { - for (&id, node) in &self.board.nodes { + let board = self.board.borrow(); + for (&id, node) in &board.nodes { let color = if Some(id) == self.selected_node { Color32::RED } else { @@ -169,7 +181,7 @@ impl BoardBuilderApp { ); let stroke = Stroke { width: 1.0, color: Color32::BLACK }; for edge in &node.edges { - let other_node = &self.board.nodes[edge]; + let other_node = &board.nodes[edge]; painter.line_segment( [view.from_coords(node.x, node.y), view.from_coords(other_node.x, other_node.y)], stroke, @@ -178,6 +190,52 @@ impl BoardBuilderApp { } } + fn draw_edit_labels_dialog(&mut self, ctx: &Context) { + Window::new("Edit Labels") + .collapsible(false) + .show(ctx, |ui| { + let mut board = self.board.borrow_mut(); + let selected_label_key = &mut self.edit_labels_dialog.selected_label_key; + let selected_label_value = &mut self.edit_labels_dialog.selected_label_value; + ui.columns(2, |col| { + col[0].group(|ui| { + for key_label in board.labels.keys() { + ui.selectable_value(selected_label_key, key_label.clone(), key_label); + } + }); + col[0].horizontal(|ui| { + if ui.button("+").clicked() { + self.edit_labels_dialog.add_key_dialog.show(); + } + if ui.button("-").clicked() { + todo!(); + } + }); + col[1].group(|ui| { + if let Some(value_labels) = board.labels.get(selected_label_key) { + for value_label in value_labels { + ui.selectable_value(selected_label_value, value_label.clone(), value_label); + } + } + }); + col[1].horizontal(|ui| { + if ui.button("+").clicked() { + todo!(); + } + if ui.button("-").clicked() { + todo!(); + } + }); + }); + if self.edit_labels_dialog.add_key_dialog.open { + if let StringDialogResponse::Accepted(key) = + self.edit_labels_dialog.add_key_dialog.ui(ui, "Add Key") { + board.labels.insert(key, Vec::new()); + } + } + }); + } + fn dispatch_click(&mut self, btn: PointerButton, x: f32, y: f32) { use EditMode::*; use PointerButton::*; @@ -190,18 +248,20 @@ impl BoardBuilderApp { } fn select_edge(&mut self, x: f32, y: f32) { - if let Some(nearest_id) = self.board.nearest_node(x, y) { + let mut board = self.board.borrow_mut(); + if let Some(nearest_id) = board.nearest_node(x, y) { match self.selected_node { None => self.selected_node = Some(nearest_id), Some(id) if id == nearest_id => self.selected_node = None, - Some(id) => self.board.add_edge(id, nearest_id), + Some(id) => board.add_edge(id, nearest_id), } } } fn delete_node(&mut self, x: f32, y: f32) { - if let Some(nearest_id) = self.board.nearest_node(x, y) { - self.board.remove_node(nearest_id); + let mut board = self.board.borrow_mut(); + if let Some(nearest_id) = board.nearest_node(x, y) { + board.remove_node(nearest_id); } } @@ -234,3 +294,86 @@ impl CreateNodeDialog { self.open = false; } } + +#[derive(Default)] +struct EditLabelsDialog { + open: bool, + board: Rc>, + selected_label_key: String, + selected_label_value: String, + add_key_dialog: StringDialog, + add_value_dialog: StringDialog, +} + +impl EditLabelsDialog { + fn show(&mut self, board: Rc>) { + self.board = board; + self.open = true; + } + fn close(&mut self) { + self.open = false; + } +} + +#[derive(Default)] +struct EditNodeDialog { + open: bool, + name: String, + id: usize, + labels: HashMap, +} + +impl EditNodeDialog { + fn show(&mut self, id: usize, board: &Board) { + self.open = true; + let node = board.nodes.get(&id).unwrap(); + + self.id = id; + self.name = node.name.clone(); + self.labels = node.labels.clone(); + } +} + + +#[derive(Default)] +struct StringDialog { + string: String, + open: bool, +} + +enum StringDialogResponse { + Null, + Cancelled, + Accepted(String) +} + + +impl StringDialog { + fn show(&mut self) { + self.open = true; + self.string = String::new(); + } + + fn ui(&mut self, ui: &Ui, label: &str) -> StringDialogResponse { + match Window::new(label) + .collapsible(false) + .show(ui.ctx(), |ui| { + ui.text_edit_singleline(&mut self.string); + (ui.button("Ok"), ui.button("Cancel")) + }) { + Some(InnerResponse { inner: Some((ok, cancel)), ..}) => { + if ok.clicked() { + self.open = false; + StringDialogResponse::Accepted(self.string.clone()) + } else if cancel.clicked() { + self.open = false; + StringDialogResponse::Cancelled + } else { + StringDialogResponse::Null + } + + } + _ => StringDialogResponse::Null, + } + } +}