To follow on from the note on redo at the end of The Mighty Undoer, today I'm releasing an alpha version of Commandant which provides higher level management of side-effects. Commandant is more complicated than a simple Undoer (both internally and to implement and use) because of the issues that arise when attempting to provide robust reapplication of side-effects.
Commandant supports the managing of a chain of actions, and undoing and redoing them. To do this, it requires that all commands be defined and registered, an implementation of the Command Pattern. It also supports Transient Commands, which are commands supporting the modification of the action before completion of that action. (As an example, dragging an element in a diagram. As soon as the drag starts you know you want to move the element, but the final position will change many times before finishing into a recordable action.)
The approach of Commandant is that all modifications to a given scope should occur through the Commandant assigned to that scope. The scope could be an individual form, a scene describing a canvas, or a large interactive document. This introduces an initially large overhead of defining the interactions (which will require thinking about how they can be both done and undone), but provides a solid definition of the interactions, which has a number of benefits:
- Easier to verify how changes are made and applied to the scope.
- Once basic interactions are defined with the document, higher level interactions can be defined by composition.
- By having named interactions with your data model, making your documents scriptable by third parties is more straightforward. (You are the first consumer of your own document API.)
- Can easily serialise the actions on a document, so can support undo/redo saved to a document, providing a history of how a document was built.
- Can listen to events from the Commandant, allowing e.g. broadcast of changes to the document locally to remote clients (Future Work, straightforward)
For the code and usage documentation, please see the Commandant Repository.