-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
Hello, I was wondering if we could possibly have an example of a more complex Undo, maybe one where we a managing the state of an app with the RefCell pattern? I tried to implement Undo Redo for this simple example but could not figure it out, do you have an approach?
use undo::{Action, History};
use std::cell::RefCell;
use std::rc::Rc;
use std::error::Error;
#[derive(Clone, Debug)]
struct AppState{
names: Vec<String>
//...
}
struct AppContainer(Rc<RefCell<AppState>>);
type BoxResult<T> = Result<T,Box<Error>>;
impl AppContainer{
fn new (inner: AppState)->AppContainer{
let cl = AppState{
names: inner.names.clone(),
};
return AppContainer(Rc::new(RefCell::new(cl)));
}
fn add_name(&self, name: String){
(self.0.borrow_mut()).names.push(name);
}
fn remove_name(&self, to_remove: String){
(self.0.borrow_mut()).names.retain(|x| *x != to_remove)
}
fn names(&self)->Vec<String>{
(self.0.borrow()).names
}
}
struct AddName(String);
impl Action for AddName{
type Target = (String, AppContainer);
type Output = ();
type Error = &'static str;
fn apply(&mut self, s: (String, &mut AppContainer)) -> undo::Result<AddName> {
s.1.add_name(s.0);
Ok(())
}
fn undo(&mut self, s: (String, &mut AppContainer)) -> undo::Result<AddName> {
s.1.remove_name(s.0);
Ok(())
}
}
//inverse of AddName
struct RemoveName(String);
impl Action for RemoveName{
type Target = (String, AppContainer);
type Output = ();
type Error = &'static str;
fn apply(&mut self, s: (String, &mut AppContainer)) -> undo::Result<RemoveName> {
s.1.remove_name(s.0);
Ok(())
}
fn undo(&mut self, s: (String, &mut AppContainer)) -> undo::Result<RemoveName> {
s.1.add_name(s.0);
Ok(())
}
}
// fn main()->undo::Result<Box<dyn Action>>{
fn main(){
type Target = (String, AppContainer);
type Output = ();
type Error = &'static str;
let initial_state = AppState{
names: vec!["name 1".to_string(), "name 2".to_string()],
};
let mut history = History::new();
let container = AppContainer::new(initial_state.clone());
history.apply(&mut container, AddName("My Name".to_string())).unwrap();
dbg!(container.names());
history.apply(&mut container, RemoveName("Name 1".to_string())).unwrap();
dbg!(container.names());
// Ok(())
}
Metadata
Metadata
Assignees
Labels
No labels