Using the Undo/Redo system
This chapter will describe how to set up and use an automatic undo/redo system with the Flip framework.
Overview
The Flip framework offers a complete automatic undo/redo system. Instead of maintaining one action class per user action, adding a name (or more generally metadatas) to a transaction is sufficient for the undo/redo system to work.
Each time the client manipulate the model, a transaction is made and record all the change to the models in some kind of simple assembler. This transaction which is also a program is then sent to the server. Because the transaction might need to be rollbacked, the program and its associated assembler were made to be reversible.
The undo/redo system use exactly this system. Because the programs can be read in whatever direction, undoing is just about reading the program backward.
More subtleties were added to the undo/redo system. In particular, it tries to autocorrect the program when it is being executed to try to avoid structural problems that would make the transaction being refused by the server.
Setting Up
The Flip framework offers a class, RootBase which automatically had the undo system to the root flip class. Instead of inheriting from flip::Object , the root class will inherit from flip::RootBase .
Doing so limits just offer a single name for the stored transactions, which is very likely to be exactly what you want. If you want more metadatas to be stored along a single transaction, you may study the flip::RootBase and visit the flip::Scribe reference for more informations.
The following listing illustrate how your root class Root should be declared.
class Root |
: public ohm::flip::RootBase // instead of ohm::flip::Object |
{ |
}; |
At this point, the root Flip class will have a fully functionning undo/redo system.
Adding Metadata to a Transaction
The following listing illustrate the use of the undo/redo system in a tx_ prefixed model function.
void MyClass::tx_set_value (float val) |
{ |
Root & root = get_ancestor <Root> (); |
_tx_session_guard.prepare_record (root.use_scribe ()); // 1. |
if (!_tx_session_guard.start ()) return; |
ext_set_value (val); |
root.set_scribe_metadata ("Change Value"); // 2. |
_tx_session_guard.commit (); |
} |
- Prepare the Scribe to record : it will check-in automatically to the document
- Set the metadata for the transaction. Here this is a string that will be displayed to the user
For the undo/redo system not to record a transaction, the line 1. and 2. above just need to be removed.
Invoking the Undo/Redo System
Invoking the undo/redo system is done through the RootBase class. The Scribe maintains a pile of undo and redo transaction. Those piles are handled automatically and as the user wants it.
- has_undo method tells if some undo transaction are available
- get_undo_annotation method tells the name of the top transaction if available
- undo method actually apply the transaction at the top of the pile and place it in the redo pile
The same similar function are available for redo .