Operations and the Undo/Redo System
The iTools system provides users with the ability to interactively undo and redo actions performed on visualizations or data items. As an iTool developer, you will need to provide some code to support the undo/redo feature; the amount of code required depends largely on the type of operation your operation class performs. The main dividing line is between data-centric operations that act directly on the data that underlies a visualization, and operations that act in a more generalized way, changing some value that may not be directly related to a data item. In most cases, operations that act directly on data are based on the IDLitDataOperation class, whereas operations that are more generalized are based on the IDLitOperation class.
Data-Centric Operations
Undo/redo functionality is handled automatically for data-centric operations based on the IDLitDataOperation class. The following things happen when the user requests an operation:
- For each selected item, data that matches the type supported by the operation is extracted and passed to the operation's Execute method. The Execute method modifies the data in place. When the data changes, all visualizations that observe the data item are notified, and update accordingly.
- If the user undoes the operation, the original data values are restored. By default, the original values are cached before the Execute method is called, and undoing the operation simply retrieves the data values from the cache. If the REVERSIBLE_OPERATION property of the IDLitDataOperation object is set, however, the original values are not cached, and the UndoExecute method is called when the user undoes the operation. The UndoExecute method must exist and must reverse the action performed by the Execute method, restoring the data items to their original values. Using the REVERSIBLE_OPERATION property allows you to avoid caching the data set (which may be large) when the operation performed on the data is easily reversed by computation.
- If the user redoes the operation, the data values computed by the Execute method are restored. By default, the Execute method is simply called again. If the EXPENSIVE_COMPUTATION property of the IDLitDataOperation object is set, however, the computed values are cached after the Execute method is called, and redoing the operation simply restores the cached data values. Using the EXPENSIVE_COMPUTATION property allows you to avoid having to recompute a computationally-intensive operation each time the user undoes and then redoes the operation.
Generalized Operations
To provide undo/redo functionality, generalized operations (those based on the IDLitOperation class) must provide methods that record the initial and final values of the item being modified, along with methods that use the recorded values to undo or redo the operation. The following things happen when the user requests an operation:
- The DoAction method creates an IDLitCommandSet object to hold the initial and final values.
- The RecordInitialValues method records the original values of the specified target objects. Values are stored as data items in IDLitCommand objects, which are in turn stored in the IDLitCommandSet object.
- The RecordFinalValues method retrieves the IDLitCommand objects created by the RecordInitialValues method from the IDLitCommandSet object, and records the new values of the target objects as additional items in those IDLitCommand objects.
- If the user undoes the operation, the UndoOperation method retrieves the IDLitCommand objects from the IDLitCommandSet object, selects the relevant data items from each, and restores the values.
- If the user redoes the operation, the RedoOperation method retrieves the IDLitCommand objects from the IDLitCommandSet object, selects the relevant data items from each, and restores the values.