From c5f2ac785105d4ef906cc69a9e8e5041c16f79e5 Mon Sep 17 00:00:00 2001 From: Alberto Nidasio <alberto.nidasio@skywarder.eu> Date: Sat, 11 Jan 2025 19:19:28 +0100 Subject: [PATCH] Reorganized PID structs into submodules --- src/ui/app.rs | 4 +- src/ui/panes.rs | 2 +- src/ui/panes/pid_drawing_tool.rs | 89 ++++++++++++------- src/ui/panes/pid_drawing_tool/pid_elements.rs | 48 ---------- 4 files changed, 58 insertions(+), 85 deletions(-) delete mode 100644 src/ui/panes/pid_drawing_tool/pid_elements.rs diff --git a/src/ui/app.rs b/src/ui/app.rs index b3faad0..6947aeb 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -425,7 +425,7 @@ impl Behavior<Pane> for AppBehavior { } } -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct PaneResponse { pub action_called: Option<PaneAction>, pub drag_response: egui_tiles::UiResponse, @@ -450,7 +450,7 @@ impl Default for PaneResponse { } } -#[derive(Clone, Debug)] +#[derive(Clone)] pub enum PaneAction { SplitH, SplitV, diff --git a/src/ui/panes.rs b/src/ui/panes.rs index 0bf1385..d51fea6 100644 --- a/src/ui/panes.rs +++ b/src/ui/panes.rs @@ -13,7 +13,7 @@ use crate::mavlink::{MavMessage, TimedMessage}; use super::app::PaneResponse; -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Default, Serialize, Deserialize)] pub struct Pane { pub pane: PaneKind, } diff --git a/src/ui/panes/pid_drawing_tool.rs b/src/ui/panes/pid_drawing_tool.rs index 26150f1..c704868 100644 --- a/src/ui/panes/pid_drawing_tool.rs +++ b/src/ui/panes/pid_drawing_tool.rs @@ -1,22 +1,34 @@ -mod pid_elements; - -use egui::{epaint::PathStroke, Color32, PointerButton, Pos2, Sense, Theme, Vec2}; -use pid_elements::{PidElement, PidSymbol}; +mod connections; +mod elements; +mod pos; +mod symbols; + +use connections::Connection; +use egui::{epaint::PathStroke, Color32, CursorIcon, PointerButton, Pos2, Sense, Theme, Vec2}; +use elements::Element; +use pos::Pos; use serde::{Deserialize, Serialize}; use std::f32::consts::PI; use strum::IntoEnumIterator; +use symbols::Symbol; use crate::ui::composable_view::PaneResponse; use super::PaneBehavior; -#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq)] +/// Piping and instrumentation diagram +#[derive(Default, Clone, Serialize, Deserialize, PartialEq)] pub struct PidPane { - elements: Vec<PidElement>, + elements: Vec<Element>, + connections: Vec<Connection>, + + /// Index of the element the drag operation started on dragged: Option<usize>, - context_menu_pos: (i32, i32), + + /// Index of the element the connection operation started on connect_element: Option<usize>, - connections: Vec<(usize, usize)>, + + context_menu_pos: Pos, } impl PaneBehavior for PidPane { @@ -25,6 +37,9 @@ impl PaneBehavior for PidPane { let window_rect = ui.max_rect(); let painter = ui.painter(); + ui.ctx() + .output_mut(|output| output.cursor_icon = CursorIcon::Grab); + let theme = ui.ctx().options(|options| match options.theme_preference { egui::ThemePreference::Light => Theme::Light, egui::ThemePreference::Dark => Theme::Dark, @@ -55,13 +70,13 @@ impl PaneBehavior for PidPane { } for connection in &self.connections { - let elem1 = &self.elements[connection.0]; - let elem2 = &self.elements[connection.1]; + let elem1 = &self.elements[connection.start]; + let elem2 = &self.elements[connection.end]; - let x1 = (elem1.pos.0 + elem1.size / 2) * step_size; - let y1 = (elem1.pos.1 + elem1.size / 2) * step_size; - let x2 = (elem2.pos.0 + elem2.size / 2) * step_size; - let y2 = (elem2.pos.1 + elem2.size / 2) * step_size; + let x1 = (elem1.position.x + elem1.size / 2) * step_size; + let y1 = (elem1.position.y + elem1.size / 2) * step_size; + let x2 = (elem2.position.x + elem2.size / 2) * step_size; + let y2 = (elem2.position.y + elem2.size / 2) * step_size; painter.line_segment( [ @@ -76,8 +91,8 @@ impl PaneBehavior for PidPane { for element in &self.elements { let image_rect = egui::Rect::from_min_size( egui::Pos2::new( - (element.pos.0 * step_size) as f32, - (element.pos.1 * step_size) as f32, + (element.position.x * step_size) as f32, + (element.position.y * step_size) as f32, ), egui::Vec2::new( (element.size * step_size) as f32, @@ -85,7 +100,7 @@ impl PaneBehavior for PidPane { ), ); - egui::Image::new(element.get_image(theme)) + egui::Image::new(element.symbol.get_image(theme)) .rotate(element.rotation, Vec2::new(0.5, 0.5)) .paint_at(ui, image_rect); } @@ -94,21 +109,24 @@ impl PaneBehavior for PidPane { let pointer_pos = response .hover_pos() - .map(|pos| (pos.x as i32 / step_size, pos.y as i32 / step_size)) - .unwrap_or((0, 0)); + .map(|pos| Pos { + x: pos.x as i32 / step_size, + y: pos.y as i32 / step_size, + }) + .unwrap_or(Pos { x: 0, y: 0 }); if response.clicked_by(PointerButton::Secondary) { - self.context_menu_pos = pointer_pos; + self.context_menu_pos = pointer_pos.clone(); } response.context_menu(|ui| { ui.set_max_width(200.0); // To make sure we wrap long text - if self.is_hovering_element(self.context_menu_pos) { + if self.is_hovering_element(&self.context_menu_pos) { if ui.button("Connect").clicked() { self.connect_element = self .elements .iter() - .position(|element| element.contains(self.context_menu_pos)); + .position(|element| element.contains(&self.context_menu_pos)); ui.close_menu(); } @@ -116,7 +134,7 @@ impl PaneBehavior for PidPane { if let Some(elem) = self .elements .iter_mut() - .find(|element| element.contains(self.context_menu_pos)) + .find(|element| element.contains(&self.context_menu_pos)) { elem.rotation += PI / 2.0; } @@ -126,7 +144,7 @@ impl PaneBehavior for PidPane { if let Some(elem) = self .elements .iter_mut() - .find(|element| element.contains(self.context_menu_pos)) + .find(|element| element.contains(&self.context_menu_pos)) { elem.rotation -= PI / 2.0; } @@ -135,13 +153,13 @@ impl PaneBehavior for PidPane { } ui.menu_button("Symbols", |ui| { - for symbol in PidSymbol::iter() { + for symbol in Symbol::iter() { if ui.button(symbol.to_string()).clicked() { - self.elements.push(PidElement { - pos: self.context_menu_pos, + self.elements.push(Element { + position: self.context_menu_pos.clone(), size: 10, - symbol, rotation: 0.0, + symbol, }); ui.close_menu(); } @@ -153,11 +171,14 @@ impl PaneBehavior for PidPane { let second_connect_element = self .elements .iter() - .position(|element| element.contains(pointer_pos)); + .position(|element| element.contains(&pointer_pos)); if let (Some(elem1), Some(elem2)) = (self.connect_element, second_connect_element) { if elem1 != elem2 { - self.connections.push((elem1, elem2)); + self.connections.push(Connection { + start: elem1, + end: elem2, + }); } self.connect_element.take(); } @@ -168,14 +189,14 @@ impl PaneBehavior for PidPane { self.dragged = self .elements .iter() - .position(|element| element.contains(pointer_pos)); + .position(|element| element.contains(&pointer_pos)); } if response.dragged() { if let Some(dragged) = self.dragged { let element = &mut self.elements[dragged]; - element.pos.0 = pointer_pos.0 - element.size / 2; - element.pos.1 = pointer_pos.1 - element.size / 2; + element.position.x = pointer_pos.x - element.size / 2; + element.position.y = pointer_pos.y - element.size / 2; } } if response.drag_stopped() { @@ -191,7 +212,7 @@ impl PaneBehavior for PidPane { } impl PidPane { - fn is_hovering_element(&self, pointer_pos: (i32, i32)) -> bool { + fn is_hovering_element(&self, pointer_pos: &Pos) -> bool { self.elements .iter() .find(|element| element.contains(pointer_pos)) diff --git a/src/ui/panes/pid_drawing_tool/pid_elements.rs b/src/ui/panes/pid_drawing_tool/pid_elements.rs deleted file mode 100644 index fd571ae..0000000 --- a/src/ui/panes/pid_drawing_tool/pid_elements.rs +++ /dev/null @@ -1,48 +0,0 @@ -use egui::{ImageSource, Theme}; -use serde::{Deserialize, Serialize}; -use strum_macros::{Display, EnumIter}; - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct PidElement { - pub pos: (i32, i32), - pub size: i32, - pub symbol: PidSymbol, - pub rotation: f32, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, EnumIter, Display)] -pub enum PidSymbol { - BallValve, - CheckValve, - PressurizedVessel, -} - -impl PidElement { - pub fn contains(&self, pos: (i32, i32)) -> bool { - (pos.0 >= self.pos.0 && pos.0 < (self.pos.0 + self.size)) - && (pos.1 >= self.pos.1 && pos.1 < (self.pos.1 + self.size)) - } - - pub fn get_image(&self, theme: Theme) -> ImageSource { - match (&self.symbol, theme) { - (PidSymbol::BallValve, Theme::Light) => { - egui::include_image!("../../../../icons/ball_valve_light.svg") - } - (PidSymbol::BallValve, Theme::Dark) => { - egui::include_image!("../../../../icons/ball_valve_dark.svg") - } - (PidSymbol::CheckValve, Theme::Light) => { - egui::include_image!("../../../../icons/check_valve_light.svg") - } - (PidSymbol::CheckValve, Theme::Dark) => { - egui::include_image!("../../../../icons/check_valve_dark.svg") - } - (PidSymbol::PressurizedVessel, Theme::Light) => { - egui::include_image!("../../../../icons/pressurized_vessel_light.svg") - } - (PidSymbol::PressurizedVessel, Theme::Dark) => { - egui::include_image!("../../../../icons/pressurized_vessel_dark.svg") - } - } - } -} -- GitLab