Boost logo

Boost :

From: Andreas Nicolai (Andreas.Nicolai_at_[hidden])
Date: 2003-01-23 05:13:58


Hello there!

I just wanted to ask if there would be someone interested in a framework
library for undo/redo-functionality. In other C++ groups sometimes the
question pops up, how to implement undo-functionality. Since I've written
such thing as part of a programm of mine and since I have it "boostenised"
already, I would like to introduce it briefly. Please feel free to give me
any comments about it...

Basicly there are two classes: boost::undo_list and boost::undo_action, the
latter is an abstract base class for any undo-function you want to
provide...
Instead of describing all the details I'll just give a short example of how
one could use the library...
// ----------------------------------------------------
#include <string>
#include <iostream>
using namespace std;

#include "undo_action.hpp" // class boost::undo_action
#include "undo_list.hpp" // class boost::undo_list

#include "myown_undoactions.hpp" // contains undo-action classes

int main() {
    // 1. create the undo list somewhere
    boost::undo_list undolist;
    // 2. maybe you want to change the number of maximum undo steps
    undolist.set_maxundo(100);

    string teststring;
    teststring = "This is a simple test of the boost undo library";

    cout << "Original string: " << teststring << endl;

    // Ok, someone want's to remove a part of that string.
    // let's start with constructing the undo-action and adding that to
    // the undo list. The class StringEraseUndo is a user defined
    // undo class derived from undo_action

    // 3. create and add an undo action

    // NOTE: the constructor can look whatever the user wants it
    // to look like (see example at end of posting)
    undolist.add( new StringEraseUndo(10, 7,
        teststring.substr(10, 7), teststring) );

    // NOTE: All pointers added to the list make the objects
    // be OWNED by the list, thus the list is responsable
    // for cleaning up the memory

    // 4. perform the will-be-made-undone action
    // That means, let's finally delete that substring
    teststring.erase(10, 7);
    cout << "After erase: " << teststring << endl;

    // 5. and now let's make this undone...
    undolist.undo_last();
    cout << "After UNDO: " << teststring << endl;

    // 6. or re-done, if you like
    undolist.redo_last();
    cout << "After REDO: " << teststring << endl;
};
// ----------------------------------------------------

Well, it is obvious that the biggest problem in using the undo-library will
be the implementation of the user defined undo/redo-classes.
For the example above the class StringEraseUndo could look like this:

class StringEraseUndo : public undo_action {
  public:
    // Ctor
    StringEraseUndo(std::size_t start, std::size_t size,
        const std::string& snipped, std::string& str)
        : start_(start), size_(size), snipped_(snipped), str_(str) {};

    virtual bool undo();
    virtual void redo();

  private:
    std::size_t start_;
    std::size_t size_;
    std::string snipped_;
    std::string& str_;
};

bool StringEraseUndo::undo() {
    str_.insert(start_, snipped_);
    return true;
};

void StringEraseUndo::redo() {
    str_.erase(start_, size_);
};

However, since the undo-classes can be whatever they want to be, including
non-C++-standard stuff like GUI things, this library can be used in almost
any circumstances. The Framework, that is the undo_list and the undo_action
classes can still be written in plain C++ without having to know anything
about the users environment. This clearly qualifies these classes as a
library.

Sorry for the long text, but with just describing the system shortly it
would have caused too much confusion :-)

The library itself (that is the undo_action.hpp, undo_list.hpp and
undo_list.cpp) are ready so far. Do you think this could be a useful
addition to the boost library?

Thanks for any comments!
Bye - Andreas


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk