diff --git a/src/autorouter/autoroute.rs b/src/autorouter/autoroute.rs index a85443b..90facc5 100644 --- a/src/autorouter/autoroute.rs +++ b/src/autorouter/autoroute.rs @@ -9,6 +9,7 @@ use crate::{ board::mesadata::AccessMesadata, drawing::{band::BandTermsegIndex, graph::PrimitiveIndex}, geometry::primitive::PrimitiveShape, + layout::LayoutEdit, router::{navcord::NavcordStepper, navmesh::Navmesh, route::RouteStepper, Router}, stepper::Step, }; @@ -71,7 +72,7 @@ impl AutorouteExecutionStepper { } } -impl Step, (), AutorouteContinueStatus> +impl Step, Option, AutorouteContinueStatus> for AutorouteExecutionStepper { type Error = AutorouterError; @@ -79,14 +80,14 @@ impl Step, (), AutorouteContinueStatus> fn step( &mut self, autorouter: &mut Autorouter, - ) -> Result, AutorouterError> { + ) -> Result, AutorouteContinueStatus>, AutorouterError> { let Some(curr_ratline) = self.curr_ratline else { - return Ok(ControlFlow::Break(())); + return Ok(ControlFlow::Break(None)); }; let Some(ref mut route) = self.route else { // Shouldn't happen. - return Ok(ControlFlow::Break(())); + return Ok(ControlFlow::Break(None)); }; let (source, target) = autorouter.ratline_endpoints(curr_ratline); diff --git a/src/autorouter/compare_detours.rs b/src/autorouter/compare_detours.rs index a8ba42f..355b203 100644 --- a/src/autorouter/compare_detours.rs +++ b/src/autorouter/compare_detours.rs @@ -79,7 +79,7 @@ impl Step, (f64, f64)> for CompareDetoursExecut Ok(ControlFlow::Continue(())) } - ControlFlow::Break(()) => { + ControlFlow::Break(..) => { if let Some(next_autoroute) = self.next_autoroute.take() { autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2])?; self.autoroute = next_autoroute; diff --git a/src/autorouter/execution.rs b/src/autorouter/execution.rs index dc4f288..152175a 100644 --- a/src/autorouter/execution.rs +++ b/src/autorouter/execution.rs @@ -3,7 +3,11 @@ use std::ops::ControlFlow; use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; -use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, stepper::Step}; +use crate::{ + board::mesadata::AccessMesadata, + layout::{via::ViaWeight, LayoutEdit}, + stepper::Step, +}; use super::{ autoroute::AutorouteExecutionStepper, @@ -40,34 +44,37 @@ impl ExecutionStepper { fn step_catch_err( &mut self, autorouter: &mut Autorouter, - ) -> Result, InvokerError> { + ) -> Result, String)>, InvokerError> { Ok(match self { ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter)? { ControlFlow::Continue(..) => ControlFlow::Continue(()), - ControlFlow::Break(..) => ControlFlow::Break("finished autorouting".to_string()), + ControlFlow::Break(edit) => { + ControlFlow::Break((edit, "finished autorouting".to_string())) + } }, ExecutionStepper::PlaceVia(place_via) => { place_via.doit(autorouter)?; - ControlFlow::Break("finished placing via".to_string()) + ControlFlow::Break((None, "finished placing via".to_string())) } ExecutionStepper::RemoveBands(remove_bands) => { remove_bands.doit(autorouter)?; - ControlFlow::Break("finished removing bands".to_string()) + ControlFlow::Break((None, "finished removing bands".to_string())) } ExecutionStepper::CompareDetours(compare_detours) => { match compare_detours.step(autorouter)? { ControlFlow::Continue(()) => ControlFlow::Continue(()), - ControlFlow::Break((total_length1, total_length2)) => { - ControlFlow::Break(format!( + ControlFlow::Break((total_length1, total_length2)) => ControlFlow::Break(( + None, + format!( "total detour lengths are {} and {}", total_length1, total_length2 - )) - } + ), + )), } } ExecutionStepper::MeasureLength(measure_length) => { let length = measure_length.doit(autorouter)?; - ControlFlow::Break(format!("Total length of selected bands: {}", length)) + ControlFlow::Break((None, format!("Total length of selected bands: {}", length))) } }) } @@ -79,9 +86,9 @@ impl Step, String> for ExecutionStepper { fn step(&mut self, invoker: &mut Invoker) -> Result, InvokerError> { match self.step_catch_err(&mut invoker.autorouter) { Ok(ControlFlow::Continue(())) => Ok(ControlFlow::Continue(())), - Ok(ControlFlow::Break(msg)) => { - if let Some(command) = invoker.ongoing_command.take() { - invoker.history.do_(command); + Ok(ControlFlow::Break((maybe_edit, msg))) => { + if let (Some(command), Some(edit)) = (invoker.ongoing_command.take(), maybe_edit) { + invoker.history.do_(command, Some(edit)); } Ok(ControlFlow::Break(msg)) diff --git a/src/autorouter/history.rs b/src/autorouter/history.rs index dd6ad98..343ae40 100644 --- a/src/autorouter/history.rs +++ b/src/autorouter/history.rs @@ -6,7 +6,7 @@ use derive_getters::{Dissolve, Getters}; use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::autorouter::execution::Command; +use crate::{autorouter::execution::Command, layout::LayoutEdit}; #[derive(Error, Debug, Clone)] pub enum HistoryError { @@ -16,10 +16,18 @@ pub enum HistoryError { NoNextCommand, } +#[derive(Debug, Clone, Getters, Serialize, Deserialize)] +#[serde(transparent)] +pub struct HistoryEntry { + command: Command, + #[serde(skip)] + edit: Option, +} + #[derive(Debug, Default, Clone, Getters, Dissolve, Serialize, Deserialize)] pub struct History { - done: Vec, - undone: Vec, + done: Vec, + undone: Vec, } impl History { @@ -27,8 +35,8 @@ impl History { Self::default() } - pub fn do_(&mut self, command: Command) { - self.done.push(command); + pub fn do_(&mut self, command: Command, edit: Option) { + self.done.push(HistoryEntry { command, edit }); } pub fn undo(&mut self) -> Result<(), HistoryError> { @@ -49,15 +57,15 @@ impl History { Ok(()) } - pub fn set_undone(&mut self, iter: impl IntoIterator) { + pub fn set_undone(&mut self, iter: impl IntoIterator) { self.undone = Vec::from_iter(iter); } - pub fn last_done(&self) -> Result<&Command, HistoryError> { + pub fn last_done(&self) -> Result<&HistoryEntry, HistoryError> { self.done.last().ok_or(HistoryError::NoPreviousCommand) } - pub fn last_undone(&self) -> Result<&Command, HistoryError> { + pub fn last_undone(&self) -> Result<&HistoryEntry, HistoryError> { self.undone.last().ok_or(HistoryError::NoNextCommand) } } diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index 46ba723..ad67bd6 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -172,7 +172,7 @@ impl Invoker { #[debug_requires(self.ongoing_command.is_none())] /// Undo last command pub fn undo(&mut self) -> Result<(), InvokerError> { - let command = self.history.last_done()?; + let command = self.history.last_done()?.command(); match command { Command::Autoroute(ref selection, ..) => { @@ -194,7 +194,7 @@ impl Invoker { //#[debug_requires(self.ongoing_command.is_none())] /// Redo last command pub fn redo(&mut self) -> Result<(), InvokerError> { - let command = self.history.last_undone()?.clone(); + let command = self.history.last_undone()?.command().clone(); let mut execute = self.execute_stepper(command)?; loop { @@ -214,8 +214,8 @@ impl Invoker { pub fn replay(&mut self, history: History) { let (done, undone) = history.dissolve(); - for command in done { - self.execute(command); + for entry in done { + self.execute(entry.command().clone()); } self.history.set_undone(undone.into_iter()); diff --git a/src/geometry/edit.rs b/src/geometry/edit.rs index 775f590..0ff4308 100644 --- a/src/geometry/edit.rs +++ b/src/geometry/edit.rs @@ -22,7 +22,7 @@ pub trait ApplyGeometryEdit< fn apply(&mut self, edit: GeometryEdit); } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct GeometryEdit< PW: GetWidth + GetLayer + TryInto + TryInto + TryInto + Retag + Copy, DW: AccessDotWeight + GetLayer,