Reputation: 464
I need to create a function that undoes the previous task/addition/change. How do I do this in Borland C++?
(The program stores strings of text in a text file using "list". It is stored and then erased unless I use the save-function I've created.)
I meant creating an undo function in a simple console application by the way.
Upvotes: 7
Views: 18353
Reputation: 60065
You can store snapshots of state. State is the set of data that an action can modify. When you click undo, the current state is replaced by previous. Actually it is not a trivial task, especially if the state is complex.
Upvotes: 1
Reputation: 5585
You should check out Command Pattern.
Another reference: Using the Command pattern for undo functionality
Upvotes: 5
Reputation: 299900
I'll give yet another answer, but I think that the coverage has been insufficient so far.
The subject is far from trivial, and googling it returns a good number of results. Many applications implement a "undo" operation, and there are many variants.
There are 2 design patterns which can help us out here:
Command
: it's a reification of an actionMemento
: which consists in storing state (usually implies some form of serialization)The Command
pattern is heavily used in graphic environments because there is usually various ways to accomplish an action. Think of save in Microsoft Word for example:
And of course save is probably implemented in term of save as.
The advantage of the Command
pattern here is twofold:
undo
operationNow, there are various issues proper to undo
:
rm
on Linux or the empty trash bin action on Windows)Because there are various problems, there are various strategies:
Memento
kick in)Memento
s which consumes space, you can then use an approach which consists in only memorizing one Snapshot every 10 or 20 commands, and then redoing the commands from the latest snapshot up to the undone commandIn fact, you can probably mix Command
and Memento
at leisure, depending on the specifics of your system and thus the complexity of either.
I would only considering undoing the last action executed to begin with (using a stack of action then). The functionality of undoing whatever action the user wishes is much more complicated.
Upvotes: 17
Reputation: 3660
I've been experimenting lately on that subject. In case you don't need binary compatibility, check out https://github.com/d-led/undoredo-cpp
Upvotes: 0
Reputation: 17853
To implement Undo, you need to create an "action stack" in your application. There are two basic approaches, though:
Knowing your baseline (the last time the file was saved, or since the file was created), remember every single change that was made so that when something needs to be undone you just throw away the "top-most" item and regenerate the current view from the baseline plus all of the changes. Clicking "Redo" then just puts that item back on the stack. This has a side benefit of being able to trivially remove items anywhere in the stack without messing up other undo/redo options, although there will be special care needed to make sure that the application of "higher" states is as the user intended.
For each action, store off the change that was made to the previous state as well as the change that would be necessary to restore that previous state if you were to undo. Now when the user clicks "Undo," just do the "undo" steps. When clicking "Redo," reapply the changes that were made. In some cases the "Undo" steps will be "here's what the thing looked like before," but that can cause havoc if you want to allow users to remove items that are not on the top of the stack and then need to remove something above it.
The proper choice depends on a lot of factors, including how much data you can/will carry around. Option #1 is in some sense easier but it could become very slow to undo anything if the action stack is large.
Upvotes: 13
Reputation: 40859
Also see the memento pattern. Sometimes the intelligence that must go into a command to undo an operation is pretty involved. Drawing objects in a paint program for example. It can be easier just to store a memento and then restore from that memento to implement undo.
Upvotes: 4