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
impl UndoRedoManager
Sourcepub fn set_event_hub(&mut self, event_hub: &Arc<EventHub>)
pub fn set_event_hub(&mut self, event_hub: &Arc<EventHub>)
Inject the event hub to allow sending undo/redo related events
Sourcepub fn undo(&mut self, stack_id: Option<u64>) -> Result<()>
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.
Sourcepub fn redo(&mut self, stack_id: Option<u64>) -> Result<()>
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.
Sourcepub fn undo_if_head(
&mut self,
stack_id: Option<u64>,
seq: u64,
) -> Result<UndoStatus>
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.
Sourcepub fn begin_composite(&mut self, stack_id: Option<u64>) -> Result<()>
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 unitSourcepub fn begin_composite_labeled(
&mut self,
stack_id: Option<u64>,
label: Option<UndoLabel>,
) -> Result<()>
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.
Sourcepub fn end_composite(&mut self)
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.
pub fn cancel_composite(&mut self)
Sourcepub fn add_command(&mut self, command: Box<dyn UndoRedoCommand>)
pub fn add_command(&mut self, command: Box<dyn UndoRedoCommand>)
Adds a command to the global undo stack (ID 0).
Sourcepub fn add_command_to_stack(
&mut self,
command: Box<dyn UndoRedoCommand>,
stack_id: Option<u64>,
) -> Result<()>
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:
- If a composite command is in progress, the command is added to the composite
- If the command can be merged with the last command on the specified undo stack, they are merged
- 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.
Sourcepub fn can_undo(&self, stack_id: Option<u64>) -> bool
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.
Sourcepub fn can_redo(&self, stack_id: Option<u64>) -> bool
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.
Sourcepub fn clear_stack(&mut self, stack_id: u64)
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.
Sourcepub fn clear_all_stacks(&mut self)
pub fn clear_all_stacks(&mut self)
Clears all undo and redo history from all stacks.
Sourcepub fn create_new_stack(&mut self) -> u64
pub fn create_new_stack(&mut self) -> u64
Creates a new undo/redo stack and returns its ID.
Sourcepub fn delete_stack(&mut self, stack_id: u64) -> Result<()>
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.
Sourcepub fn get_stack_size(&self, stack_id: u64) -> usize
pub fn get_stack_size(&self, stack_id: u64) -> usize
Gets the size of the undo stack for a specific stack.
Sourcepub fn get_redo_stack_size(&self, stack_id: u64) -> usize
pub fn get_redo_stack_size(&self, stack_id: u64) -> usize
Gets the size of the redo stack for a specific stack.
Sourcepub fn last_pushed_seq(&self) -> Option<u64>
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).
Sourcepub fn head_seq(&self, stack_id: Option<u64>) -> Option<u64>
pub fn head_seq(&self, stack_id: Option<u64>) -> Option<u64>
The sequence number now on top of a stack, if any.
Sourcepub fn undo_label(&self, stack_id: Option<u64>) -> Option<UndoLabel>
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.
Sourcepub fn redo_label(&self, stack_id: Option<u64>) -> Option<UndoLabel>
pub fn redo_label(&self, stack_id: Option<u64>) -> Option<UndoLabel>
What the next redo on this stack would re-apply. See undo_label.
Sourcepub fn seal_head(&mut self, stack_id: Option<u64>)
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.
Sourcepub fn set_undo_limit(&mut self, limit: Option<usize>)
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.
Sourcepub fn undo_limit(&self) -> Option<usize>
pub fn undo_limit(&self) -> Option<usize>
The current entry limit, if one is set.