use core::fmt; use crate::{ autorouter::{history::History, selection::Selection, Autoroute, Autorouter}, drawing::rules::RulesTrait, layout::Layout, router::{EmptyRouterObserver, RouterObserverTrait}, }; #[derive(serde::Serialize, serde::Deserialize)] pub enum Command { Autoroute(Selection), } pub enum Execute { Autoroute(Autoroute), } impl Execute { pub fn next( &mut self, invoker: &mut Invoker, observer: &mut impl RouterObserverTrait, ) -> bool { match self { Execute::Autoroute(autoroute) => autoroute.step(&mut invoker.autorouter, observer), } } } pub struct Invoker { autorouter: Autorouter, history: History, } impl Invoker { pub fn new(autorouter: Autorouter) -> Self { Self { autorouter, history: History::new(), } } pub fn execute(&mut self, command: Command, observer: &mut impl RouterObserverTrait) { let mut execute = self.execute_walk(command); while execute.next(self, observer) { // } self.history.set_undone(std::iter::empty()); } pub fn execute_walk(&mut self, command: Command) -> Execute { let execute = self.dispatch_command(&command); self.history.do_(command); execute } fn dispatch_command(&self, command: &Command) -> Execute { match command { Command::Autoroute(ref selection) => { Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap()) } } } pub fn undo(&mut self) { let command = self.history.done().last().unwrap(); match command { Command::Autoroute(ref selection) => self.autorouter.undo_autoroute(selection), } 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 replay(&mut self, history: History) { let (done, undone) = history.destructure(); for command in done { self.execute(command, &mut EmptyRouterObserver); } self.history.set_undone(undone.into_iter()); } pub fn autorouter(&self) -> &Autorouter { &self.autorouter } pub fn history(&self) -> &History { &self.history } }