Contains the infrastructure for model manipulation routines that are
undoable, atomic, and trigger layout after finishing.
Package Specification
Every routine that manipulates the UML model or the DI model
must inherit from Command, so that the routine is undoable.
Every command must implement the redo and undo
methods, and remember the appropriate information in the
constructor or in the lazyInit routine.
A command may be a MacroCommand, ie, consist of several
sub-commands, but still be undoable in one step.
Memorizing information in Commands
No command may ever hold references to UML elements or DI elements
directly. Attributes such as
private UmlClass myClass;
are strictly forbidden. The reason is that in a later command, the
element may be deleted; when the user undoes the delete command,
the element is not the same (referentially spoken), only content-wise.
The only thing that remains stable over multiple create/delete steps
is the SmId or the DiId (assumed that the create/delete commands
work correctly, which we assume).
You may only hold references to SmIds or DiIds!
MacroCommands and element access
Your command may be used as a part of a MacroCommand. Eg, the first
command may be "create Foo", and your command may be "set Foo's color
to blue". In the constructor of your command, Foo does not exist yet!
So you cannot read Foo's color in order to set this color in the undo
call. You have to do this in lazyInit. This method is called after all
previous commands in the MacroCommand have been executed and just before
your command's redo is called. So Foo does exist in this moment, and
you can set the value here.
Example
- Constructor receives a DiId and a color. Store them in
private variables in your command. Do not retrieve the DI element to
the given DiId, as it may not exist yet.
- lazyInit retrieves the DI element to the DiId and stores its current
color in a private variable.
- redo retrieves the DI element to the DiId and sets the color to
the color given in the constructor.
- redo retrieves the DI element to the DiId and sets the color to
the color found in lazyInit.
Assume that in the following command, the recently colored element is
removed. Then, you hit undo - the element reappears and has the same
DiId as before (because the redo and undo routines of the delete command
were written correctly). Then, undo again - and the DiId that you stored in your
command's constructor above is resolved, and the color you retrieved in
lazyInit is set for this element. All is fine.