Command is an implementation of the command pattern, in which objects are used to represent actions. A command object typically has an execute() method that runs its action, and sometimes will have an undo() method if it can be reversed.
// -> alerts "Hello world!"
Note the general pattern here: we create a subclass of Command. This new subclass accepts a drawing context to instantiate it (ctx), chooses some random drawing points, then uses this.callSuper to pass some command properties up to the Command initialize() method. Note that the random numbers are generated once, rather than every time the command is executed: each new DrawCircleCommand does something different, but an individual DrawCircleCommand instance ought to do the same thing every time it is executed.
This command will not work properly if you try to hook it up to a command stack as described below.
Of course, this is more useful when you have lots of different types of commands that can all be undone, and you want to provide a means of stepping through the command stack.
stepTo() lets you revert to any point in the stack’s command history by number. stepTo(0) undoes the whole stack, and commands are numbered sequentially from 1 upwards.
Some commands cannot easily be undone, but you’d still like to store them in a stack. One example is the circle-drawing command shown above: it’s hard to ‘unpaint’ a circle because you don’t know what filled its space before it was there. In some situations it’s easier to implement ‘undo’ by having a stack redo itself from the start up to a given point. If you pass a redo command when creating a stack, the stack will assume you want a redo-from-start stack and will automatically call your redo command to wipe the slate clean before running its history again.
That could easily be hooked up to an interface button, as could a snippet of code for calling drawingStack.undo().
The advantage of coding the application like this is that you can add as many different types of drawing command as you like without complicating the mechanism for undoing them – you just get all your commands to notify a single command stack and use that stack to revert changes.
Notice how the command gives itself a name property inside its initialize() method – this will allow us to represent the command in the GUI in the next example.
This creates a list that updates itself in response to stack changes. Your subscribe callback is passed a reference to the stack whenever the stack executes a new command or undoes/redoes a command. Stacks have a pointer property that tells you what point in the stack the most recent command is. So you can work out whether each command has been undone or not, and assign a greyed-out color to commands after the current pointer position. Your forEach callback is passed each command in the stack in turn, along with its position in the stack (beginning at 0).