Undo is implemented in order to erase the last change done, reverting it to an older state or reversing the command that was done to the model being edited. With the possibility of undo, users can explore and work without fear of making mistakes, because they can easily be undone.
Gaphor makes use of the undo system in Gaphas, which is Gaphor’s Canvas widget. Gaphas implements this undo system by storing the reverse operations to an undo list. For example, if you add a new item to the screen, it will save the remove operation to the undo list. If undo is then called, Gaphas will then remove the item from the screen that was added.
Overview of Transactions
Gaphor adds on to what Gaphas provides with an undo service, called the Undo
Manager. The Undo Manager works transactionally. This means that if something is
being updated by the user in a model, each change is divided into operations
called transactions. Each operation must succeed or fail as a complete unit. If
the transaction fails in the middle, it is rolled back. In Gaphor this is
achieved by the
transaction module, which provides a decorator called
@transactional. Methods then make use of this decorator, and the undo data is
stored in a transaction once the method is called. For example, pasting data in
the model using the
copyservice module and setting a value on an object’s
property page both create new transactions.
When transactions take place, they also emit event notifications on the key transaction milestones so that other services can make use of the events. The event notifications are for the begin of the transaction, and the commit of the transaction if it is successful or the rollback of the transaction if it fails. Please see the next sections for more detail on how these event notifications work during a transaction.
Start of a Transaction
Transactionobject is created.
TransactionBeginevent is emitted.
UndoManagerinstantiates a new
ActionStackwhich is the transaction object, and adds the undo action to the stack.
Nested transactions are supported to allow a transaction to be added inside of another transaction that is already in progress.
TransactionCommitevent is emitted
UndoManagercloses and stores the transaction.
TransactionRollbackevent is emitted. TransactionRollback event is emitted
UndoManagerplays back all the recorded actions and then stops listening.