public class UndoEngine extends Object
The UndoEngine
is in charge of recording
, managing
and executing
single units of work that can be undone and redone, represented by the interface
IUndoUnit
.
These units are managed in a queue-like structure and can be added manually to the queue by calling the addUnit(IUndoUnit)
method.
Executing the units is done by client code or commands by calling undo()
or
redo()
. The engine automatically manages the queue so that calling these two methdos will consistently move
the units in the queue.
The beginCompoundEdit(String, String)
method allows to record units by bracketing serveral changes in an
ICompoundEdit
. Implementations of the ICompoundEdit
interface record all subsequent changes until it
is committed
and therefore all recorded units are added to the engine. For more
information and examples see ICompoundEdit
.
Depending on the properties UnitMergingEnabled
and
AutoMergeTime
, the engine tries to collapse added IUndoUnit
s if possible. This
enhances the performance and reduces the required memory for undo changes. For example, when a node is moved
interactively, instead of saving every position that the node had when being dragged the engine will only hold one IUndoUnit
at the end to undo the entire movement.
Customizing Undo/Redo
IUndoUnit
or subclass
UndoUnitBase
. The client application needs to encapsulate
changes in this implementation and provide the logic to completely undo and redo these changes.
Instances of your custom IUndoUnit
implementations need to be added to the UndoEngine
manually via addUnit(IUndoUnit)
.
IUndoUnit
s for each intermediate step and merge them in the end.
In such cases client code should implement IMementoSupport
instead.
See the documentation of IMementoSupport
for examples and guidelines on how to implement
this memento design pattern concept.
UndoEngine
unless you want to customize the internal
handling of the units, which is both complicated and prone to errors. In most use cases it is sufficient
to provide custom IUndoUnit
s or IMementoSupport
.
IUndoUnit
,
AbstractUndoUnit
,
IMementoSupport
,
ICompoundEdit
Constructor and Description |
---|
UndoEngine()
Initializes a new instance of the
UndoEngine class. |
Modifier and Type | Method and Description |
---|---|
void |
addPropertyChangedListener(IEventHandler<PropertyChangedEventArgs> propertyChangedEvent)
|
void |
addUnit(IUndoUnit unit)
Adds a new
IUndoUnit to the queue. |
void |
addUnitRedoneListener(IEventHandler<IEventArgs> unitRedoneEvent)
Adds the given listener for the
UnitRedone event that occurs when the engine has successfully executed the IUndoUnit.redo()
operation of an IUndoUnit . |
void |
addUnitUndoneListener(IEventHandler<IEventArgs> unitUndoneEvent)
Adds the given listener for the
UnitUndone event that occurs when the engine has successfully executed the IUndoUnit.undo()
operation of an IUndoUnit . |
ICompoundEdit |
beginCompoundEdit(String undoName,
String redoName)
Begins a compound edit that will use the provided name.
|
boolean |
canRedo()
Determines whether a call to
redo() can be made. |
boolean |
canUndo()
Determines whether a call to
undo() can be made. |
void |
clear()
Clears the internal queue and
disposes all units in it. |
Duration |
getAutoMergeTime()
Gets the duration during which the engine will try to merge newly added units.
|
String |
getRedoName()
|
int |
getSize()
Gets the maximum size of the undo queue this instance is managing.
|
Object |
getToken()
Returns a token that can be used to store and compare the state of the undo queue.
|
String |
getUndoName()
|
boolean |
isPerformingRedo()
Indicates whether this instance is currently performing a redo operation.
|
boolean |
isPerformingUndo()
Indicates whether this instance is currently performing an undo operation.
|
boolean |
isUnitMergingEnabled()
Gets a value that indicates whether or not this instance should try to merge newly added units.
|
protected void |
onPropertyChanged(String name)
This will trigger the corresponding
PropertyChanged event. |
void |
redo()
Redoes the next
IUndoUnit . |
void |
removePropertyChangedListener(IEventHandler<PropertyChangedEventArgs> propertyChangedEvent)
|
void |
removeUnitRedoneListener(IEventHandler<IEventArgs> unitRedoneEvent)
Removes the given listener for the
UnitRedone event that occurs when the engine has successfully executed the IUndoUnit.redo()
operation of an IUndoUnit . |
void |
removeUnitUndoneListener(IEventHandler<IEventArgs> unitUndoneEvent)
Removes the given listener for the
UnitUndone event that occurs when the engine has successfully executed the IUndoUnit.undo()
operation of an IUndoUnit . |
void |
setAutoMergeTime(Duration value)
Sets the duration during which the engine will try to merge newly added units.
|
void |
setSize(int value)
Sets the maximum size of the undo queue this instance is managing.
|
void |
setUnitMergingEnabled(boolean value)
Sets a value that indicates whether or not this instance should try to merge newly added units.
|
String |
toString() |
void |
undo()
Undoes the next
IUndoUnit . |
public UndoEngine()
UndoEngine
class.public final void addPropertyChangedListener(IEventHandler<PropertyChangedEventArgs> propertyChangedEvent)
PropertyChanged
event that occurs when canUndo()
, canRedo()
,
UndoName
, or RedoName
changed its value.propertyChangedEvent
- The listener to add.removePropertyChangedListener(IEventHandler)
public void addUnit(IUndoUnit unit)
IUndoUnit
to the queue.
This implementation will automatically group multiple units into a single unit if the time since the last add is less
than AutoMergeTime
.
unit
- The unit of work to add.public final void addUnitRedoneListener(IEventHandler<IEventArgs> unitRedoneEvent)
UnitRedone
event that occurs when the engine has successfully executed the IUndoUnit.redo()
operation of an IUndoUnit
.unitRedoneEvent
- The listener to add.removeUnitRedoneListener(IEventHandler)
public final void addUnitUndoneListener(IEventHandler<IEventArgs> unitUndoneEvent)
UnitUndone
event that occurs when the engine has successfully executed the IUndoUnit.undo()
operation of an IUndoUnit
.unitUndoneEvent
- The listener to add.removeUnitUndoneListener(IEventHandler)
public ICompoundEdit beginCompoundEdit(String undoName, String redoName)
public boolean canRedo()
redo()
can be made.public boolean canUndo()
undo()
can be made.public void clear()
disposes
all units in it.public final Duration getAutoMergeTime()
If this is set to Duration.ZERO
, the engine will try to merge incoming units depending on the UnitMergingEnabled
property. Otherwise, if the time span between the last added unit and the new unit exceeds the set value, the engine
does not try to merge the units regardless what the UnitMergingEnabled
property is set
to. Likewise, if the time span is smaller than the set value, the engine will always try to merge units.
setAutoMergeTime(Duration)
public final String getRedoName()
public final int getSize()
A size of 0
effectively disables this implementation.
setSize(int)
public Object getToken()
E.g. an application can retrieve the token once the user has saved his document. Comparing the token returned by this instance with another one retrieved at a later point in time enables the application to determine whether the document is in the same state.
Object.equals(Object)
method.public final String getUndoName()
public final boolean isPerformingRedo()
public final boolean isPerformingUndo()
public final boolean isUnitMergingEnabled()
If true
this instance will try to merge
or replace
units in the queue. Note that when the AutoMergeTime
property is set to Duration.ZERO
and this property is set to true
, the engine will always try to merge incoming units. Otherwise the AutoMergeTime
dictates whether the engine will try to merge a unit or not.
setUnitMergingEnabled(boolean)
protected void onPropertyChanged(String name)
PropertyChanged
event.name
- The name of the property that changed.public void redo()
IUndoUnit
.UnsupportedOperationException
- If an undo operation is already in progress.RuntimeException
- If canRedo()
would yield false
.public final void removePropertyChangedListener(IEventHandler<PropertyChangedEventArgs> propertyChangedEvent)
PropertyChanged
event that occurs when canUndo()
,
canRedo()
, UndoName
, or RedoName
changed its value.propertyChangedEvent
- The listener to remove.addPropertyChangedListener(IEventHandler)
public final void removeUnitRedoneListener(IEventHandler<IEventArgs> unitRedoneEvent)
UnitRedone
event that occurs when the engine has successfully executed the IUndoUnit.redo()
operation of an IUndoUnit
.unitRedoneEvent
- The listener to remove.addUnitRedoneListener(IEventHandler)
public final void removeUnitUndoneListener(IEventHandler<IEventArgs> unitUndoneEvent)
UnitUndone
event that occurs when the engine has successfully executed the IUndoUnit.undo()
operation of an IUndoUnit
.unitUndoneEvent
- The listener to remove.addUnitUndoneListener(IEventHandler)
public final void setAutoMergeTime(Duration value)
If this is set to Duration.ZERO
, the engine will try to merge incoming units depending on the UnitMergingEnabled
property. Otherwise, if the time span between the last added unit and the new unit exceeds the set value, the engine
does not try to merge the units regardless what the UnitMergingEnabled
property is set
to. Likewise, if the time span is smaller than the set value, the engine will always try to merge units.
value
- The AutoMergeTime to set.getAutoMergeTime()
public final void setSize(int value)
A size of 0
effectively disables this implementation.
value
- The Size to set.getSize()
public final void setUnitMergingEnabled(boolean value)
If true
this instance will try to merge
or replace
units in the queue. Note that when the AutoMergeTime
property is set to Duration.ZERO
and this property is set to true
, the engine will always try to merge incoming units. Otherwise the AutoMergeTime
dictates whether the engine will try to merge a unit or not.
value
- The UnitMergingEnabled to set.isUnitMergingEnabled()
public void undo()
IUndoUnit
.UnsupportedOperationException
- If an undo operation is already in progress.RuntimeException
- If canUndo()
would yield false
.