Can add a label key
This commit is contained in:
parent
767af41736
commit
1eeb59a4ac
@ -8,6 +8,9 @@ use rfd::FileDialog;
|
|||||||
use board_builder::{ Board, CoordTransformer, read_board_from_file, write_board_to_file };
|
use board_builder::{ Board, CoordTransformer, read_board_from_file, write_board_to_file };
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let native_options = eframe::NativeOptions::default();
|
let native_options = eframe::NativeOptions::default();
|
||||||
@ -16,12 +19,13 @@ fn main() {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct BoardBuilderApp {
|
struct BoardBuilderApp {
|
||||||
board: Board,
|
board: Rc<RefCell<Board>>,
|
||||||
texture: Option<TextureHandle>,
|
texture: Option<TextureHandle>,
|
||||||
image: Option<image::DynamicImage>,
|
image: Option<image::DynamicImage>,
|
||||||
edit_mode: EditMode,
|
edit_mode: EditMode,
|
||||||
create_node_dialog: CreateNodeDialog,
|
|
||||||
selected_node: Option<usize>,
|
selected_node: Option<usize>,
|
||||||
|
create_node_dialog: CreateNodeDialog,
|
||||||
|
edit_labels_dialog: EditLabelsDialog,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -41,16 +45,17 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
menu::bar(ui, |ui| {
|
menu::bar(ui, |ui| {
|
||||||
ui.menu_button("File", |ui| {
|
ui.menu_button("File", |ui| {
|
||||||
if ui.button("New").clicked() {
|
if ui.button("New").clicked() {
|
||||||
self.board = Board::default();
|
self.board.replace(Board::default());
|
||||||
self.texture = None;
|
self.texture = None;
|
||||||
self.image = None;
|
self.image = None;
|
||||||
self.edit_mode = EditMode::Nodes;
|
self.edit_mode = EditMode::Nodes;
|
||||||
|
ui.close_menu();
|
||||||
}
|
}
|
||||||
if ui.button("Open...").clicked() {
|
if ui.button("Open...").clicked() {
|
||||||
if let Some(board_file) = FileDialog::new().pick_file() {
|
if let Some(board_file) = FileDialog::new().pick_file() {
|
||||||
match read_board_from_file(&board_file) {
|
match read_board_from_file(&board_file) {
|
||||||
Ok((board, image)) => {
|
Ok((board, image)) => {
|
||||||
self.board = board;
|
self.board.replace(board);
|
||||||
match image {
|
match image {
|
||||||
None => { self.image = None; self.texture = None }
|
None => { self.image = None; self.texture = None }
|
||||||
Some(image) => self.load_image(ctx, image),
|
Some(image) => self.load_image(ctx, image),
|
||||||
@ -59,10 +64,11 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
Err(_) => panic!("Could not open file!"),
|
Err(_) => panic!("Could not open file!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ui.close_menu();
|
||||||
}
|
}
|
||||||
if ui.button("Save As...").clicked() {
|
if ui.button("Save As...").clicked() {
|
||||||
if let Some(board_file) = FileDialog::new().save_file() {
|
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() {
|
if ui.button("Open Image...").clicked() {
|
||||||
@ -82,7 +88,7 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
self.edit_mode = EditMode::Edges;
|
self.edit_mode = EditMode::Edges;
|
||||||
}
|
}
|
||||||
if ui.button("Edit Labels...").clicked() {
|
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")
|
Window::new("Create Node")
|
||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
|
let mut board = self.board.borrow_mut();
|
||||||
ui.label("Name:");
|
ui.label("Name:");
|
||||||
ui.text_edit_singleline(&mut self.create_node_dialog.name);
|
ui.text_edit_singleline(&mut self.create_node_dialog.name);
|
||||||
if ui.button("Add").clicked() {
|
if ui.button("Add").clicked() {
|
||||||
self.create_node_dialog.close();
|
self.create_node_dialog.close();
|
||||||
self.board.add_node(
|
board.add_node(
|
||||||
self.create_node_dialog.x,
|
self.create_node_dialog.x,
|
||||||
self.create_node_dialog.y,
|
self.create_node_dialog.y,
|
||||||
self.create_node_dialog.name.clone(),
|
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> {
|
fn load_image_file(&mut self, ctx: &Context, image_file: &Path) -> Result<(), image::ImageError> {
|
||||||
let image = image::io::Reader::open(image_file)?.decode()?;
|
let image = image::io::Reader::open(image_file)?.decode()?;
|
||||||
self.load_image(ctx, image);
|
self.load_image(ctx, image);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +165,8 @@ impl BoardBuilderApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw_board(&self, painter: &Painter, view: View) {
|
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 {
|
let color = if Some(id) == self.selected_node {
|
||||||
Color32::RED
|
Color32::RED
|
||||||
} else {
|
} else {
|
||||||
@ -169,7 +181,7 @@ 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 = &self.board.nodes[edge];
|
let other_node = &board.nodes[edge];
|
||||||
painter.line_segment(
|
painter.line_segment(
|
||||||
[view.from_coords(node.x, node.y), view.from_coords(other_node.x, other_node.y)],
|
[view.from_coords(node.x, node.y), view.from_coords(other_node.x, other_node.y)],
|
||||||
stroke,
|
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) {
|
fn dispatch_click(&mut self, btn: PointerButton, x: f32, y: f32) {
|
||||||
use EditMode::*;
|
use EditMode::*;
|
||||||
use PointerButton::*;
|
use PointerButton::*;
|
||||||
@ -190,18 +248,20 @@ impl BoardBuilderApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn select_edge(&mut self, x: f32, y: f32) {
|
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 {
|
match self.selected_node {
|
||||||
None => self.selected_node = Some(nearest_id),
|
None => self.selected_node = Some(nearest_id),
|
||||||
Some(id) if id == nearest_id => self.selected_node = None,
|
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) {
|
fn delete_node(&mut self, x: f32, y: f32) {
|
||||||
if let Some(nearest_id) = self.board.nearest_node(x, y) {
|
let mut board = self.board.borrow_mut();
|
||||||
self.board.remove_node(nearest_id);
|
if let Some(nearest_id) = board.nearest_node(x, y) {
|
||||||
|
board.remove_node(nearest_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,3 +294,86 @@ impl CreateNodeDialog {
|
|||||||
self.open = false;
|
self.open = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct EditLabelsDialog {
|
||||||
|
open: bool,
|
||||||
|
board: Rc<RefCell<Board>>,
|
||||||
|
selected_label_key: String,
|
||||||
|
selected_label_value: String,
|
||||||
|
add_key_dialog: StringDialog,
|
||||||
|
add_value_dialog: StringDialog,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EditLabelsDialog {
|
||||||
|
fn show(&mut self, board: Rc<RefCell<Board>>) {
|
||||||
|
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<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user