Source code for Karana.KUtils.MultibodyTUI.history
from typing import TypeVar, Generic
State = TypeVar("State")
[docs]
class StateHistory(Generic[State]):
"""Container for a state object with undo and redo capabilities"""
def __init__(self, init_state: State):
"""StateHistory constructor
Parameters
----------
init_state: State
The initial state
"""
self._stack = [init_state]
self._redo_stack = []
@property
def state(self) -> State:
"""The current state"""
return self._stack[-1]
@state.setter
def state(self, state: State):
"""Set a new state"""
self.push(state)
[docs]
def push(self, state: State):
"""Set a new state"""
if state == self.state:
return state
self._stack.append(state)
if self._redo_stack:
self._redo_stack = []
@property
def current_state_count(self) -> int:
"""The number of states in the undo stack
Note that this includes the current state and is always
positive.
"""
return len(self._stack)
@property
def total_state_count(self) -> int:
"""The number of states - past, present, and future
This is similar to past_state_count but also includes states in
the redo stack.
"""
return len(self._stack) + len(self._redo_stack)
[docs]
def undo_stack_size(self) -> int:
"""The number of states in the undo stack
Note that this includes the current state and is always positive
"""
return len(self._stack)
[docs]
def can_undo(self) -> bool:
"""Return whether an undo state is available"""
return len(self._stack) > 1
[docs]
def undo(self):
"""Return to the previous state"""
if not self.can_undo():
return
self._redo_stack.append(self._stack.pop())
[docs]
def can_redo(self) -> bool:
"""Return whether a redo state is available"""
return bool(self._redo_stack)
[docs]
def redo(self):
"""Return to the next state (ie: undo a previous undo)"""
if not self.can_redo():
return
self._stack.append(self._redo_stack.pop())