I just need to implement the undo/redo using command pattern for graphics object. It will be nice if any one can add a sample program or would like to add functionalists to given code in this link webpage.
It will very kind if any one can provide a sample example link to this.
Design Patterns: Elements of Reusable Object-Oriented Software The key to this pattern is an abstract Command class, which declares an interface for executing operations.
So basically what would be the simplest implementation is that you first need to declare an abstract class that will be extended in each concrete command:
Now each concrete command would extend this class and implement the two methods. Suppose you have a command that would add a graphics object to your drawing:
Note that you would have to keep some additional information for each concrete command. In the previous example, you would have to keep at least information about the graphics object to be added/removed from the model.
Now to keep track of each command so you can enable user to undo/redo, there are a few approaches you can choose.
The first approach would be to define one stack (say UndoStack) where you would put commands to be enabled for undo operation; similarly you would define another stack (say RedoStack) for redo operation. Upon each command execution you would push the command object to UndoStack. When user wants to undo the operation, you would pop command from that stack, invoke undoCommand() on popped object and push it on RedoStack. A similar process applies to redo operation - you pop command from RedoStack, invoke doCommand() and push it to UndoStack. It may sound confusing now, but you can write the process down as a simple algorithm to get a better idea of how it really works.
Another approach that comes to my mind is not to have two stacks, but one command manager (or whatever better name comes to your mind) with list containing command objects (e.g. ArrayList<AbstractCommand>). When you execute the command you would just add it to the end of this list. If you choose this approach you would also declare another variable in your command manager class, say currentCommand. That would be an integer variable that would act as a "pointer" to the last command executed (basically, it's just an index to the command in your list). Upon undo action you would get the last command from your list, invoke undoCommand() on that object and decrement currentCommand so you are now pointed to previous one; similarly upon redo action you would invoke redoCommand() on the current object from the list and increment currentCommand so you are now pointed to the next one. This approach might be a little more complex, but it's interesting to implement for practice.
Hope this was helpful. Try to make something out of these guidelines and come back for some more details if necessary.
The quieter you are, the more you are able to hear.
Joined: Nov 22, 2012
Thanks Kemal. I will try to implement the way you have explained and will let you know.
Joined: Nov 22, 2012
Hi Everyone and Kemal,
Yes kemal's answer was helpful but can I have any link that explain how undo/redo can be achieved for graphics object. Any simple example. at least drawing of two figures circle and line will do. That can help me in designing my application in much better and understandable way.
You have to decouple your code so that your paintComponent method and the data from which it paints are separate. In other words, you have an underlying data structure which you are editing. (This means, separate the model from the view.) Then your Edit object would contain references to the old version of the data and the new version of the data. The "undo" method would replace the underlying data structure with the old version and then repaint, and the "redo" method would replace the underlying data structure with the new version and then repaing.
If you're going to implement undo and redo, I strongly suggest you use the existing javax.swing.undo package rather than inventing your own undo and redo processing. In this case you would be extending the UndoableEdit class. You might also find that the "command" you use for the undo and redo methods should just modify the underlying data structure instead of replacing the whole thing.