TSE3::Cmd namespace contains classes that implement a
GoF Command pattern. You can use this in applications that use the
TSE3 library to provide a command history with undo/redo facilities.
However, in order to use these classes there are a number of provisos
that you must take care to note:
- The commands
There is a
TSE3::Cmd class for every useful operation
Song data structure and it's subcomponents. There
are not commands for alterations to the state of objects like
Metronome since they are
system wide settings, not
CommandHistory class holds the list of commands.
For any operation, you create a
Command object for it
execute() on the command,
add it to the
For now on you can call
redo on the
CommandHistory to undo/redo the history of operations.
Remember that your application will be kept up to date with the
resulting changes to the
Song through the
Notifier interface mechanism.
If you support multiple
Song objects in your application
you can either use one
CommandHistory class for all
operations, or create a separate
Song. It is this latter operation that is the most
logical, and the
contains support for it.
- If you use commands, don't directly use the TSE3 API
If you are using TSE3 Commands then any change to a
or it's subcomponents must be done through commands. Otherwise,
if the state of the
Song changes between a command
results may occur.
- Writing your own commands
If you implement your own commands that are creational or destrutional
(if that is a word ;-) you must take care. If you, for example, create
execute you should not
delete it in
undo and then create a different
Part in a subsequent call to
If any subsequent commands act on that
Part and take a
Part* parameter to identify it, by deleting the
Part and creating a new different one on a 'redo' you
will cause the later command to be invalid.
Creational patterns should create objects in the constructors,
put them into the
Song in undo, and delete the object
in the destructor only if the object is deleted after having
Destructional commands should merely remove the object in
execute and put the same object back in in
undo. The object may only be deleted in the destructor
if the command has not been undone.
However, despite these provisos and the extra care that you must take when
using the command pattern in your application, the benefits are great:
the undo/redo facility is a really user-friendly useful facility that sets
a good application appart from a great one.