Struct undo::UndoStack
[−]
[src]
pub struct UndoStack<'a, E> { /* fields omitted */ }
Maintains a stack of UndoCmd
s.
UndoStack
uses dynamic dispatch so it can hold multiple types of commands at a given time.
It will notice when it's state changes to either dirty or clean, and call the user defined methods set in on_clean and on_dirty. This is useful if you want to trigger some event when the state changes, eg. enabling and disabling buttons in an ui.
The PopCmd
given in the examples below is defined as:
#[derive(Clone, Copy)] struct PopCmd { vec: *mut Vec<i32>, e: Option<i32>, } impl UndoCmd for PopCmd { type Err = (); fn redo(&mut self) -> undo::Result<()> { self.e = unsafe { let ref mut vec = *self.vec; vec.pop() }; Ok(()) } fn undo(&mut self) -> undo::Result<()> { unsafe { let ref mut vec = *self.vec; let e = self.e.ok_or(())?; vec.push(e); } Ok(()) } }
Methods
impl<'a, E: 'a> UndoStack<'a, E>
[src]
fn new() -> UndoStack<'a, E>
fn with_limit(limit: usize) -> UndoStack<'a, E>
Creates a new UndoStack
with a limit on how many UndoCmd
s can be stored in the stack.
If this limit is reached it will start popping of commands at the bottom of the stack when
pushing new commands on to the stack. No limit is set by default which means it may grow
indefinitely.
The stack may remove multiple commands at a time to increase performance.
Panics
Panics if limit
is 0.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::with_limit(2); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.push(cmd)?; stack.push(cmd)?; // Pops off the first cmd. assert!(vec.is_empty()); stack.undo()?; stack.undo()?; stack.undo()?; // Does nothing. assert_eq!(vec, vec![1, 2]);
fn with_capacity(capacity: usize) -> UndoStack<'a, E>
Creates a new UndoStack
with the specified capacity.
Examples
let stack = UndoStack::<()>::with_capacity(10); assert_eq!(stack.capacity(), 10);
fn with_capacity_and_limit(capacity: usize, limit: usize) -> UndoStack<'a, E>
Creates a new UndoStack
with the specified capacity and limit.
Panics
Panics if limit
is 0.
Examples
let stack = UndoStack::<()>::with_capacity_and_limit(10, 10); assert_eq!(stack.capacity(), 10); assert_eq!(stack.limit(), Some(10));
fn limit(&self) -> Option<usize>
Returns the limit of the UndoStack
, or None
if it has no limit.
Examples
let stack = UndoStack::<()>::with_limit(10); assert_eq!(stack.limit(), Some(10)); let stack = UndoStack::<()>::new(); assert_eq!(stack.limit(), None);
fn capacity(&self) -> usize
Returns the number of commands the stack can hold without reallocating.
Examples
let stack = UndoStack::<()>::with_capacity(10); assert_eq!(stack.capacity(), 10);
fn reserve(&mut self, additional: usize)
Reserves capacity for at least additional
more commands to be inserted in the given stack.
The stack may reserve more space to avoid frequent reallocations.
Panics
Panics if the new capacity overflows usize.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::new(); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.reserve(10); assert!(stack.capacity() >= 11);
fn shrink_to_fit(&mut self)
Shrinks the capacity of the UndoStack
as much as possible.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::with_capacity(10); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.push(cmd)?; stack.push(cmd)?; assert_eq!(stack.capacity(), 10); stack.shrink_to_fit(); assert!(stack.capacity() >= 3);
fn on_clean<F>(&mut self, f: F) where F: FnMut() + 'a
Sets what should happen if the state changes from dirty to clean.
By default the UndoStack
does nothing when the state changes.
Note: An empty stack is clean, so the first push will not trigger this method.
Examples
let mut vec = vec![1, 2, 3]; let x = Cell::new(0); let mut stack = UndoStack::new(); stack.on_clean(|| x.set(1)); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.undo()?; assert_eq!(x.get(), 0); stack.redo()?; assert_eq!(x.get(), 1);
fn on_dirty<F>(&mut self, f: F) where F: FnMut() + 'a
Sets what should happen if the state changes from clean to dirty.
By default the UndoStack
does nothing when the state changes.
Examples
let mut vec = vec![1, 2, 3]; let x = Cell::new(0); let mut stack = UndoStack::new(); stack.on_dirty(|| x.set(1)); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; assert_eq!(x.get(), 0); stack.undo()?; assert_eq!(x.get(), 1);
fn is_clean(&self) -> bool
Returns true
if the state of the stack is clean, false
otherwise.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::new(); let cmd = PopCmd { vec: &mut vec, e: None }; assert!(stack.is_clean()); // An empty stack is always clean. stack.push(cmd)?; assert!(stack.is_clean()); stack.undo()?; assert!(!stack.is_clean());
fn is_dirty(&self) -> bool
Returns true
if the state of the stack is dirty, false
otherwise.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::new(); let cmd = PopCmd { vec: &mut vec, e: None }; assert!(!stack.is_dirty()); // An empty stack is always clean. stack.push(cmd)?; assert!(!stack.is_dirty()); stack.undo()?; assert!(stack.is_dirty());
fn push<T>(&mut self, cmd: T) -> Result<E> where T: UndoCmd<Err=E> + 'a
Pushes cmd
to the top of the stack and executes its redo
method.
This pops off all other commands above the active command from the stack.
If cmd
s id is equal to the top command on the stack, the two commands are merged.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::new(); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.push(cmd)?; stack.push(cmd)?; assert!(vec.is_empty());
fn redo(&mut self) -> Result<E>
Calls the redo
method for the active UndoCmd
and sets the next UndoCmd
as the new
active one.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::new(); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.push(cmd)?; stack.push(cmd)?; assert!(vec.is_empty()); stack.undo()?; stack.undo()?; stack.undo()?; assert_eq!(vec, vec![1, 2, 3]); stack.redo()?; stack.redo()?; stack.redo()?; assert!(vec.is_empty());
fn undo(&mut self) -> Result<E>
Calls the undo
method for the active UndoCmd
and sets the previous UndoCmd
as the
new active one.
Examples
let mut vec = vec![1, 2, 3]; let mut stack = UndoStack::new(); let cmd = PopCmd { vec: &mut vec, e: None }; stack.push(cmd)?; stack.push(cmd)?; stack.push(cmd)?; assert!(vec.is_empty()); stack.undo()?; stack.undo()?; stack.undo()?; assert_eq!(vec, vec![1, 2, 3]);