egui: implement loading the history (not functional yet)

Committing this non-functional and half-baked because loading the
history requires implementing stateful deserialization, which is quite
an effort to implement with Serde, as there are no applicable derive
macros.
This commit is contained in:
Mikolaj Wielgus 2024-05-23 18:59:29 +02:00
parent 02bfe1105b
commit 53fa89d02c
4 changed files with 42 additions and 1 deletions

View File

@ -16,6 +16,10 @@ impl History {
} }
} }
pub fn destructure(self) -> (Vec<Command>, Vec<Command>) {
(self.done, self.undone)
}
pub fn do_(&mut self, command: Command) { pub fn do_(&mut self, command: Command) {
self.done.push(command); self.done.push(command);
} }
@ -30,6 +34,10 @@ impl History {
self.done.push(command); self.done.push(command);
} }
pub fn set_undone(&mut self, iter: impl IntoIterator<Item = Command>) {
self.undone = Vec::from_iter(iter);
}
pub fn done(&self) -> &[Command] { pub fn done(&self) -> &[Command] {
&self.done &self.done
} }

View File

@ -1,6 +1,9 @@
use core::fmt;
use crate::{ use crate::{
autorouter::{history::History, selection::Selection, Autoroute, Autorouter}, autorouter::{history::History, selection::Selection, Autoroute, Autorouter},
drawing::rules::RulesTrait, drawing::rules::RulesTrait,
layout::Layout,
router::{EmptyRouterObserver, RouterObserverTrait}, router::{EmptyRouterObserver, RouterObserverTrait},
}; };
@ -44,6 +47,8 @@ impl<R: RulesTrait> Invoker<R> {
while execute.next(self, observer) { while execute.next(self, observer) {
// //
} }
self.history.set_undone(std::iter::empty());
} }
pub fn execute_walk(&mut self, command: Command) -> Execute { pub fn execute_walk(&mut self, command: Command) -> Execute {
@ -81,6 +86,16 @@ impl<R: RulesTrait> Invoker<R> {
self.history.redo(); 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<R> { pub fn autorouter(&self) -> &Autorouter<R> {
&self.autorouter &self.autorouter
} }

View File

@ -1,3 +1,4 @@
use core::fmt;
use std::collections::HashSet; use std::collections::HashSet;
use crate::{ use crate::{

View File

@ -197,6 +197,23 @@ impl eframe::App for App {
ui.separator(); 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 ui.button("Save history").clicked() {
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();
@ -208,7 +225,7 @@ impl eframe::App for App {
let path = file_handle.path(); let path = file_handle.path();
let mut file = File::create(path).unwrap(); let mut file = File::create(path).unwrap();
let mut invoker = invoker_arc_mutex.lock().unwrap(); let mut invoker = invoker_arc_mutex.lock().unwrap();
serde_json::to_writer(file, invoker.history()); serde_json::to_writer_pretty(file, invoker.history());
} }
}); });
} }