diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 1aa44f4..ae5aeac 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -14,6 +14,7 @@ use super::{ autoroute::Autoroute, place_via::PlaceVia, ratsnest::{Ratsnest, RatvertexIndex}, + remove_bands::RemoveBands, selection::{BandSelection, PinSelection}, }; @@ -89,7 +90,27 @@ impl Autorouter { PlaceVia::new(weight) } - pub fn undo_place_via(&mut self, weight: ViaWeight) { + pub fn undo_place_via(&mut self, _weight: ViaWeight) { + todo!(); + } + + pub fn remove_bands(&mut self, selection: &BandSelection) -> Result<(), AutorouterError> { + for selector in selection.selectors() { + let band = self.board.bandname_band(selector.band.clone()).unwrap().0; + self.board.layout_mut().remove_band(band); + } + + Ok(()) + } + + pub fn remove_bands_walk( + &self, + selection: &BandSelection, + ) -> Result { + RemoveBands::new(selection) + } + + pub fn undo_remove_bands(&mut self, _selection: &BandSelection) { todo!(); } diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index 69b07fe..1fb504e 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -15,6 +15,7 @@ use super::{ autoroute::Autoroute, history::{History, HistoryError}, place_via::PlaceVia, + remove_bands::RemoveBands, selection::{BandSelection, PinSelection}, Autorouter, AutorouterError, AutorouterStatus, }; @@ -57,12 +58,14 @@ pub enum InvokerStatus { pub enum Command { Autoroute(PinSelection), PlaceVia(ViaWeight), + RemoveBands(BandSelection), } #[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts, GetObstacles)] pub enum Execute { Autoroute(Autoroute), PlaceVia(PlaceVia), + RemoveBands(RemoveBands), } impl Execute { @@ -99,6 +102,10 @@ impl Execute { place_via.doit(&mut invoker.autorouter)?; Ok(InvokerStatus::Finished) } + Execute::RemoveBands(remove_bands) => { + remove_bands.doit(&mut invoker.autorouter)?; + Ok(InvokerStatus::Finished) + } } } } @@ -210,6 +217,9 @@ impl Invoker { Command::PlaceVia(weight) => Ok::(Execute::PlaceVia( self.autorouter.place_via_walk(*weight)?, )), + Command::RemoveBands(selection) => Ok::(Execute::RemoveBands( + self.autorouter.remove_bands_walk(selection)?, + )), } } @@ -220,6 +230,7 @@ impl Invoker { match command { Command::Autoroute(ref selection) => self.autorouter.undo_autoroute(selection), Command::PlaceVia(weight) => self.autorouter.undo_place_via(*weight), + Command::RemoveBands(ref selection) => self.autorouter.undo_remove_bands(selection), } Ok::<(), InvokerError>(self.history.undo()?) diff --git a/src/autorouter/mod.rs b/src/autorouter/mod.rs index 092afce..03e299d 100644 --- a/src/autorouter/mod.rs +++ b/src/autorouter/mod.rs @@ -4,6 +4,7 @@ pub mod history; pub mod invoker; pub mod place_via; pub mod ratsnest; +pub mod remove_bands; pub mod selection; pub use autorouter::*; diff --git a/src/autorouter/place_via.rs b/src/autorouter/place_via.rs index f0cf97a..fe4250d 100644 --- a/src/autorouter/place_via.rs +++ b/src/autorouter/place_via.rs @@ -14,18 +14,27 @@ use super::{ #[derive(Debug)] pub struct PlaceVia { weight: ViaWeight, + done: bool, } impl PlaceVia { pub fn new(weight: ViaWeight) -> Result { - Ok(Self { weight }) + Ok(Self { + weight, + done: false, + }) } pub fn doit( &mut self, autorouter: &mut Autorouter, ) -> Result<(), AutorouterError> { - autorouter.place_via(self.weight) + if !self.done { + self.done = true; + autorouter.place_via(self.weight) + } else { + Ok(()) + } } } diff --git a/src/autorouter/remove_bands.rs b/src/autorouter/remove_bands.rs new file mode 100644 index 0000000..edeafc0 --- /dev/null +++ b/src/autorouter/remove_bands.rs @@ -0,0 +1,63 @@ +use crate::{ + board::mesadata::AccessMesadata, + drawing::graph::PrimitiveIndex, + geometry::primitive::PrimitiveShape, + router::{navmesh::Navmesh, trace::Trace}, +}; + +use super::{ + invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, + selection::BandSelection, + Autorouter, AutorouterError, +}; + +#[derive(Debug)] +pub struct RemoveBands { + selection: BandSelection, + done: bool, +} + +impl RemoveBands { + pub fn new(selection: &BandSelection) -> Result { + Ok(Self { + selection: selection.clone(), + done: false, + }) + } + + pub fn doit( + &mut self, + autorouter: &mut Autorouter, + ) -> Result<(), AutorouterError> { + if !self.done { + self.done = true; + autorouter.remove_bands(&self.selection) + } else { + Ok(()) + } + } +} + +impl GetMaybeNavmesh for RemoveBands { + fn maybe_navmesh(&self) -> Option<&Navmesh> { + None + } +} + +impl GetMaybeTrace for RemoveBands { + fn maybe_trace(&self) -> Option<&Trace> { + None + } +} + +impl GetGhosts for RemoveBands { + fn ghosts(&self) -> &[PrimitiveShape] { + &[] + } +} + +impl GetObstacles for RemoveBands { + fn obstacles(&self) -> &[PrimitiveIndex] { + &[] + } +} diff --git a/src/autorouter/selection.rs b/src/autorouter/selection.rs index 345e145..e10f9e1 100644 --- a/src/autorouter/selection.rs +++ b/src/autorouter/selection.rs @@ -15,8 +15,8 @@ use crate::{ #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] pub struct PinSelector { - pin: String, - layer: String, + pub pin: String, + pub layer: String, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -78,11 +78,15 @@ impl PinSelection { self.node_selector(board, node) .map_or(false, |selector| self.selectors.contains(&selector)) } + + pub fn selectors(&self) -> impl Iterator { + self.selectors.iter() + } } #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] pub struct BandSelector { - band: BandName, + pub band: BandName, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -133,6 +137,10 @@ impl BandSelection { self.node_selector(board, node) .map_or(false, |selector| self.selectors.contains(&selector)) } + + pub fn selectors(&self) -> impl Iterator { + self.selectors.iter() + } } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/bin/topola-egui/top.rs b/src/bin/topola-egui/top.rs index f5dc512..4aab9b4 100644 --- a/src/bin/topola-egui/top.rs +++ b/src/bin/topola-egui/top.rs @@ -75,6 +75,11 @@ impl Top { egui::Modifiers::CTRL, egui::Key::P, )); + let mut remove_bands = Trigger::new(Action::new( + "Remove Selected Bands", + egui::Modifiers::NONE, + egui::Key::Delete, + )); let mut undo = Trigger::new(Action::new("Undo", egui::Modifiers::CTRL, egui::Key::Z)); let mut redo = Trigger::new(Action::new("Redo", egui::Modifiers::CTRL, egui::Key::Y)); @@ -104,6 +109,8 @@ impl Top { place_via.toggle_widget(ctx, ui, &mut self.is_placing_via); + remove_bands.button(ctx, ui); + ui.separator(); undo.button(ctx, ui); @@ -213,6 +220,22 @@ impl Top { } } } else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) { + } else if remove_bands.consume_key_triggered(ctx, ui) { + if maybe_execute.as_mut().map_or(true, |execute| { + matches!(execute.maybe_status(), Some(InvokerStatus::Finished)) + }) { + if let (Some(invoker), Some(ref mut overlay)) = ( + arc_mutex_maybe_invoker.lock().unwrap().as_mut(), + maybe_overlay, + ) { + let selection = overlay.selection().clone(); + overlay.clear_selection(); + maybe_execute + .insert(ExecuteWithStatus::new(invoker.execute_walk( + Command::RemoveBands(selection.band_selection), + )?)); + } + } } else if undo.consume_key_triggered(ctx, ui) { if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() { invoker.undo(); diff --git a/src/board/board.rs b/src/board/board.rs index eacebec..6671638 100644 --- a/src/board/board.rs +++ b/src/board/board.rs @@ -156,6 +156,10 @@ impl Board { self.band_bandname.get_by_left(&band) } + pub fn bandname_band(&self, bandname: BandName) -> Option<&BandUid> { + self.band_bandname.get_by_right(&bandname) + } + pub fn try_set_band_between_nodes( &mut self, source: FixedDotIndex, diff --git a/src/drawing/band.rs b/src/drawing/band.rs index 0a76d06..c7bfa66 100644 --- a/src/drawing/band.rs +++ b/src/drawing/band.rs @@ -16,7 +16,7 @@ use super::{ }; #[derive(Debug, Hash, Clone, Copy)] -pub struct BandUid(BandTermsegIndex, BandTermsegIndex); +pub struct BandUid(pub BandTermsegIndex, pub BandTermsegIndex); impl BandUid { pub fn new(first_seg1: BandTermsegIndex, first_seg2: BandTermsegIndex) -> Self {