mirror of https://codeberg.org/topola/topola.git
autorouter: encapsulate command history in a `History` object
This commit is contained in:
parent
8999fcb160
commit
fb501ac072
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 redo(&mut self, observer: &mut impl RouterObserverTrait<R>) {
|
pub fn undo(&mut self) {
|
||||||
let command = self.undone_history.pop().unwrap();
|
let command = self.history.done().last().unwrap();
|
||||||
self.execute(command, observer);
|
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<R> {
|
pub fn autorouter(&self) -> &Autorouter<R> {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue