autorouter: encapsulate command history in a `History` object

This commit is contained in:
Mikolaj Wielgus 2024-05-22 01:12:55 +02:00
parent 8999fcb160
commit fb501ac072
6 changed files with 73 additions and 31 deletions

View File

@ -35,7 +35,7 @@ pub struct Autoroute {
impl Autoroute { impl Autoroute {
pub fn new( pub fn new(
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static, ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
autorouter: &mut Autorouter<impl RulesTrait>, autorouter: &Autorouter<impl RulesTrait>,
) -> Option<Self> { ) -> Option<Self> {
let mut ratlines_iter = Box::new(ratlines.into_iter()); let mut ratlines_iter = Box::new(ratlines.into_iter());
@ -146,7 +146,7 @@ impl<R: RulesTrait> Autorouter<R> {
} }
} }
pub fn autoroute_walk(&mut self, selection: &Selection) -> Option<Autoroute> { pub fn autoroute_walk(&self, selection: &Selection) -> Option<Autoroute> {
Autoroute::new(self.selected_ratlines(selection), self) Autoroute::new(self.selected_ratlines(selection), self)
} }

37
src/autorouter/history.rs Normal file
View File

@ -0,0 +1,37 @@
use crate::autorouter::invoker::Command;
pub struct History {
done: Vec<Command>,
undone: Vec<Command>,
}
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
}
}

View File

@ -1,9 +1,10 @@
use crate::{ use crate::{
autorouter::{selection::Selection, Autoroute, Autorouter}, autorouter::{history::History, selection::Selection, Autoroute, Autorouter},
drawing::rules::RulesTrait, drawing::rules::RulesTrait,
router::RouterObserverTrait, router::{EmptyRouterObserver, RouterObserverTrait},
}; };
#[derive(serde::Serialize, serde::Deserialize)]
pub enum Command { pub enum Command {
Autoroute(Selection), Autoroute(Selection),
} }
@ -26,16 +27,14 @@ impl Execute {
pub struct Invoker<R: RulesTrait> { pub struct Invoker<R: RulesTrait> {
autorouter: Autorouter<R>, autorouter: Autorouter<R>,
history: Vec<Command>, history: History,
undone_history: Vec<Command>,
} }
impl<R: RulesTrait> Invoker<R> { impl<R: RulesTrait> Invoker<R> {
pub fn new(autorouter: Autorouter<R>) -> Self { pub fn new(autorouter: Autorouter<R>) -> Self {
Self { Self {
autorouter, autorouter,
history: vec![], history: History::new(),
undone_history: vec![],
} }
} }
@ -48,31 +47,39 @@ impl<R: RulesTrait> Invoker<R> {
} }
pub fn execute_walk(&mut self, command: Command) -> Execute { pub fn execute_walk(&mut self, command: Command) -> Execute {
let execute = match command { let execute = self.dispatch_command(&command);
Command::Autoroute(ref selection) => { self.history.do_(command);
Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap())
}
};
self.history.push(command);
execute execute
} }
pub fn undo(&mut self) { fn dispatch_command(&self, command: &Command) -> Execute {
let command = self.history.pop().unwrap();
match command { match command {
Command::Autoroute(ref selection) => { Command::Autoroute(ref selection) => {
self.autorouter.undo_autoroute(selection); Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap())
}
} }
} }
self.undone_history.push(command); 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) {
//
} }
pub fn redo(&mut self, observer: &mut impl RouterObserverTrait<R>) { self.history.undo();
let command = self.undone_history.pop().unwrap(); }
self.execute(command, observer);
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<R> { pub fn autorouter(&self) -> &Autorouter<R> {

View File

@ -1,4 +1,5 @@
mod autorouter; mod autorouter;
pub mod history;
pub mod invoker; pub mod invoker;
pub mod ratsnest; pub mod ratsnest;
pub mod selection; pub mod selection;

View File

@ -6,10 +6,12 @@ use crate::{
layout::{zone::ZoneWeight, Layout, NodeIndex}, layout::{zone::ZoneWeight, Layout, NodeIndex},
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Selection { pub struct Selection {
pins: HashSet<String>, pins: HashSet<String>,
#[serde(skip)]
primitives: HashSet<PrimitiveIndex>, primitives: HashSet<PrimitiveIndex>,
#[serde(skip)]
zones: HashSet<GenericIndex<ZoneWeight>>, zones: HashSet<GenericIndex<ZoneWeight>>,
} }

View File

@ -260,12 +260,7 @@ impl eframe::App for App {
{ {
if let Some(invoker_arc_mutex) = &self.invoker { if let Some(invoker_arc_mutex) = &self.invoker {
let invoker_arc_mutex = invoker_arc_mutex.clone(); let invoker_arc_mutex = invoker_arc_mutex.clone();
execute(async move { execute(async move { invoker_arc_mutex.lock().unwrap().redo() });
invoker_arc_mutex
.lock()
.unwrap()
.redo(&mut EmptyRouterObserver);
});
} }
} }