Skip to main content

UndoRedoManager

Struct UndoRedoManager 

Source
pub struct UndoRedoManager { /* private fields */ }
Expand description

Manager for undo and redo operations.

The UndoRedoManager maintains multiple stacks of commands:

  • Each stack has an undo stack for commands that can be undone
  • Each stack has a redo stack for commands that have been undone and can be redone

It also supports:

  • Grouping multiple commands as a single unit using begin_composite/end_composite
  • Merging commands of the same type when appropriate
  • Switching between different stacks

Implementations§

Source§

impl UndoRedoManager

Source

pub fn new() -> Self

Creates a new empty UndoRedoManager with one default stack (ID 0).

Source

pub fn set_event_hub(&mut self, event_hub: &Arc<EventHub>)

Inject the event hub to allow sending undo/redo related events

Source

pub fn undo(&mut self, stack_id: Option<u64>) -> Result<()>

Undoes the most recent command on the specified stack. If stack_id is None, the global stack (ID 0) is used.

The undone command is moved to the redo stack. Returns Ok(()) if successful or if there are no commands to undo.

Source

pub fn redo(&mut self, stack_id: Option<u64>) -> Result<()>

Redoes the most recently undone command on the specified stack. If stack_id is None, the global stack (ID 0) is used.

The redone command is moved back to the undo stack. Returns Ok(()) if successful or if there are no commands to redo.

Source

pub fn undo_if_head( &mut self, stack_id: Option<u64>, seq: u64, ) -> Result<UndoStatus>

Undo only if seq still names the top of the stack.

The affordance this exists for is a toast’s Undo button: it is offered for one specific operation, and between the offer and the click anything may have pushed — an autosave, a second window, a background job. Plain undo() would take back that later thing instead, silently and with the user believing they undid what the toast named. Naming the operation turns a wrong action into an honest UndoStatus::Superseded.

Source

pub fn begin_composite(&mut self, stack_id: Option<u64>) -> Result<()>

Begins a composite command group.

All commands added between begin_composite and end_composite will be treated as a single command. This is useful for operations that logically represent a single action but require multiple commands to implement.

§Example
let mut manager = UndoRedoManager::new();
manager.begin_composite();
manager.add_command(Box::new(Command1::new()));
manager.add_command(Box::new(Command2::new()));
manager.end_composite();
// Now undo() will undo both commands as a single unit
Source

pub fn begin_composite_labeled( &mut self, stack_id: Option<u64>, label: Option<UndoLabel>, ) -> Result<()>

begin_composite, naming what the group is.

Worth the extra call: a group’s constituent labels describe its parts, so a menu built from them reads “Undo update” for what the writer experienced as “add a character to the story bible”. Only the caller that opened the group knows the answer.

Source

pub fn end_composite(&mut self)

Ends the current composite command group and adds it to the specified undo stack.

If no commands were added to the composite, nothing is added to the undo stack. If this is a nested composite, only the outermost composite is added to the undo stack.

Source

pub fn cancel_composite(&mut self)

Source

pub fn add_command(&mut self, command: Box<dyn UndoRedoCommand>)

Adds a command to the global undo stack (ID 0).

Source

pub fn add_command_to_stack( &mut self, command: Box<dyn UndoRedoCommand>, stack_id: Option<u64>, ) -> Result<()>

Adds a command to the specified undo stack. If stack_id is None, the global stack (ID 0) is used.

This method handles several cases:

  1. If a composite command is in progress, the command is added to the composite
  2. If the command can be merged with the last command on the specified undo stack, they are merged
  3. Otherwise, the command is added to the specified undo stack as a new entry

In all cases, the redo stack of the stack is cleared when a new command is added.

Source

pub fn can_undo(&self, stack_id: Option<u64>) -> bool

Returns true if there are commands that can be undone on the specified stack. If stack_id is None, the global stack (ID 0) is used.

Source

pub fn can_redo(&self, stack_id: Option<u64>) -> bool

Returns true if there are commands that can be redone on the specified stack. If stack_id is None, the global stack (ID 0) is used.

Source

pub fn clear_stack(&mut self, stack_id: u64)

Clears the undo and redo history for a specific stack.

This method removes all commands from both the undo and redo stacks of the specified stack.

Source

pub fn clear_all_stacks(&mut self)

Clears all undo and redo history from all stacks.

Source

pub fn create_new_stack(&mut self) -> u64

Creates a new undo/redo stack and returns its ID.

Source

pub fn delete_stack(&mut self, stack_id: u64) -> Result<()>

Deletes an undo/redo stack by its ID.

The default stack (ID 0) cannot be deleted.

Source

pub fn get_stack_size(&self, stack_id: u64) -> usize

Gets the size of the undo stack for a specific stack.

Source

pub fn get_redo_stack_size(&self, stack_id: u64) -> usize

Gets the size of the redo stack for a specific stack.

Source

pub fn last_pushed_seq(&self) -> Option<u64>

The sequence number of the entry the most recent push landed in.

Read it immediately after the call that pushed — it is how a caller learns the number to hand to undo_if_head later, and every later push overwrites it. None after a push that recorded nothing (an untracked stack, or a command folded into an open composite).

Source

pub fn head_seq(&self, stack_id: Option<u64>) -> Option<u64>

The sequence number now on top of a stack, if any.

Source

pub fn undo_label(&self, stack_id: Option<u64>) -> Option<UndoLabel>

What the next undo on this stack would take back, as a machine key for the application to translate. None when the stack is empty or the command declined to name itself.

Source

pub fn redo_label(&self, stack_id: Option<u64>) -> Option<UndoLabel>

What the next redo on this stack would re-apply. See undo_label.

Source

pub fn seal_head(&mut self, stack_id: Option<u64>)

Close the top entry to merging, so the next command starts a new one.

Merging exists so a burst of typing is one undo step. It decides purely on the shape of two commands — adjacent, close in time, same kind — and cannot see that something unrelated happened in between. So type, rename a chapter from another panel, type again, and the two bursts merge across the rename: one undo then takes back text entered before an event the writer remembers as a dividing line.

A caller that knows such a line was crossed says so here. Idempotent, and a no-op on an empty or missing stack.

Source

pub fn set_undo_limit(&mut self, limit: Option<usize>)

Bound how many entries a stack keeps, dropping the oldest past the limit. None (the default) is unbounded.

Unbounded is right for a document that lives as long as its window and wrong for a session measured in hours: every entry may pin a snapshot of the store, so an uncapped stack has no ceiling at all. Applied on the next push, not retroactively.

Source

pub fn undo_limit(&self) -> Option<usize>

The current entry limit, if one is set.

Trait Implementations§

Source§

impl Debug for UndoRedoManager

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for UndoRedoManager

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.