diff --git a/src/autorouter/history.rs b/src/autorouter/history.rs index 8f75972..2a686bb 100644 --- a/src/autorouter/history.rs +++ b/src/autorouter/history.rs @@ -16,6 +16,10 @@ impl History { } } + pub fn destructure(self) -> (Vec, Vec) { + (self.done, self.undone) + } + pub fn do_(&mut self, command: Command) { self.done.push(command); } @@ -30,6 +34,10 @@ impl History { self.done.push(command); } + pub fn set_undone(&mut self, iter: impl IntoIterator) { + self.undone = Vec::from_iter(iter); + } + pub fn done(&self) -> &[Command] { &self.done } diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index 3bd830b..410396b 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -1,6 +1,9 @@ +use core::fmt; + use crate::{ autorouter::{history::History, selection::Selection, Autoroute, Autorouter}, drawing::rules::RulesTrait, + layout::Layout, router::{EmptyRouterObserver, RouterObserverTrait}, }; @@ -44,6 +47,8 @@ impl Invoker { while execute.next(self, observer) { // } + + self.history.set_undone(std::iter::empty()); } pub fn execute_walk(&mut self, command: Command) -> Execute { @@ -81,6 +86,16 @@ impl Invoker { 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 } diff --git a/src/autorouter/selection.rs b/src/autorouter/selection.rs index dfaa586..b376fe1 100644 --- a/src/autorouter/selection.rs +++ b/src/autorouter/selection.rs @@ -1,3 +1,4 @@ +use core::fmt; use std::collections::HashSet; use crate::{ diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 4166a38..b1ae749 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -197,6 +197,23 @@ impl eframe::App for App { ui.separator(); + if ui.button("Load history").clicked() { + if let Some(invoker_arc_mutex) = &self.invoker { + let invoker_arc_mutex = invoker_arc_mutex.clone(); + let ctx = ui.ctx().clone(); + let task = rfd::AsyncFileDialog::new().pick_file(); + + execute(async move { + if let Some(file_handle) = task.await { + let path = file_handle.path(); + let mut file = File::open(path).unwrap(); + let mut invoker = invoker_arc_mutex.lock().unwrap(); + invoker.replay(serde_json::from_reader(file).unwrap()); + } + }); + } + } + if ui.button("Save history").clicked() { if let Some(invoker_arc_mutex) = &self.invoker { let invoker_arc_mutex = invoker_arc_mutex.clone(); @@ -208,7 +225,7 @@ impl eframe::App for App { let path = file_handle.path(); let mut file = File::create(path).unwrap(); let mut invoker = invoker_arc_mutex.lock().unwrap(); - serde_json::to_writer(file, invoker.history()); + serde_json::to_writer_pretty(file, invoker.history()); } }); }