diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 8c112b9..0467762 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -35,7 +35,7 @@ pub struct Autoroute { impl Autoroute { pub fn new( ratlines: impl IntoIterator> + 'static, - autorouter: &mut Autorouter, + autorouter: &Autorouter, ) -> Option { let mut ratlines_iter = Box::new(ratlines.into_iter()); @@ -146,7 +146,7 @@ impl Autorouter { } } - pub fn autoroute_walk(&mut self, selection: &Selection) -> Option { + pub fn autoroute_walk(&self, selection: &Selection) -> Option { Autoroute::new(self.selected_ratlines(selection), self) } diff --git a/src/autorouter/history.rs b/src/autorouter/history.rs new file mode 100644 index 0000000..63e6829 --- /dev/null +++ b/src/autorouter/history.rs @@ -0,0 +1,37 @@ +use crate::autorouter::invoker::Command; + +pub struct History { + done: Vec, + undone: Vec, +} + +impl History { + pub fn new() -> Self { + Self { + done: vec![], + undone: vec![], + } + } + + pub fn do_(&mut self, command: Command) { + self.done.push(command); + } + + pub fn undo(&mut self) { + let command = self.done.pop().unwrap(); + self.undone.push(command); + } + + pub fn redo(&mut self) { + let command = self.undone.pop().unwrap(); + self.done.push(command); + } + + pub fn done(&self) -> &[Command] { + &self.done + } + + pub fn undone(&self) -> &[Command] { + &self.undone + } +} diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index d785069..3641b6c 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -1,9 +1,10 @@ use crate::{ - autorouter::{selection::Selection, Autoroute, Autorouter}, + autorouter::{history::History, selection::Selection, Autoroute, Autorouter}, drawing::rules::RulesTrait, - router::RouterObserverTrait, + router::{EmptyRouterObserver, RouterObserverTrait}, }; +#[derive(serde::Serialize, serde::Deserialize)] pub enum Command { Autoroute(Selection), } @@ -26,16 +27,14 @@ impl Execute { pub struct Invoker { autorouter: Autorouter, - history: Vec, - undone_history: Vec, + history: History, } impl Invoker { pub fn new(autorouter: Autorouter) -> Self { Self { autorouter, - history: vec![], - undone_history: vec![], + history: History::new(), } } @@ -48,31 +47,39 @@ impl Invoker { } pub fn execute_walk(&mut self, command: Command) -> Execute { - let execute = match command { - Command::Autoroute(ref selection) => { - Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap()) - } - }; - - self.history.push(command); + let execute = self.dispatch_command(&command); + self.history.do_(command); execute } - pub fn undo(&mut self) { - let command = self.history.pop().unwrap(); - + fn dispatch_command(&self, command: &Command) -> Execute { match command { Command::Autoroute(ref selection) => { - self.autorouter.undo_autoroute(selection); + Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap()) } } - - self.undone_history.push(command); } - pub fn redo(&mut self, observer: &mut impl RouterObserverTrait) { - let command = self.undone_history.pop().unwrap(); - self.execute(command, observer); + pub fn undo(&mut self) { + let command = self.history.done().last().unwrap(); + let mut execute = self.dispatch_command(command); + + while execute.next(self, &mut EmptyRouterObserver) { + // + } + + self.history.undo(); + } + + pub fn redo(&mut self) { + let command = self.history.undone().last().unwrap(); + let mut execute = self.dispatch_command(command); + + while execute.next(self, &mut EmptyRouterObserver) { + // + } + + self.history.redo(); } pub fn autorouter(&self) -> &Autorouter { diff --git a/src/autorouter/mod.rs b/src/autorouter/mod.rs index a891d0f..41fb8d7 100644 --- a/src/autorouter/mod.rs +++ b/src/autorouter/mod.rs @@ -1,4 +1,5 @@ mod autorouter; +pub mod history; pub mod invoker; pub mod ratsnest; pub mod selection; diff --git a/src/autorouter/selection.rs b/src/autorouter/selection.rs index 45fa5e4..dfaa586 100644 --- a/src/autorouter/selection.rs +++ b/src/autorouter/selection.rs @@ -6,10 +6,12 @@ use crate::{ layout::{zone::ZoneWeight, Layout, NodeIndex}, }; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Selection { pins: HashSet, + #[serde(skip)] primitives: HashSet, + #[serde(skip)] zones: HashSet>, } diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 39cd2e8..c100480 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -260,12 +260,7 @@ impl eframe::App for App { { if let Some(invoker_arc_mutex) = &self.invoker { let invoker_arc_mutex = invoker_arc_mutex.clone(); - execute(async move { - invoker_arc_mutex - .lock() - .unwrap() - .redo(&mut EmptyRouterObserver); - }); + execute(async move { invoker_arc_mutex.lock().unwrap().redo() }); } }