Functorized Undo/Redo

One day, I was looking for the Undo/Redo algorithm to be used in my future project. Among different resources, I found DDJ, [1], where Al Stevens presented the template-based algorithm of Undo/Redo actions.

As far I got (unfortunately, on the Net there is no article available, just the source code at http://www.ddj.com/ftp/1998/1998_11/cprog118.txt), its implementation addresses mostly document editors. Typical actions are: Insert, Delete, & Replace. The code seemed interesting, but its using was not obvious.

The idea to marry the algorithm with the functor was encouraging. So, this article presents what I eventually got.

Tested Software

The code was tested with MS Visual C++ 2003 and Windows 2000. Generally, you may run the code in any environment: Win32, Unix, ... Your compiler should be good with templates.

Source Code

undo.h: (modified Al Stevens code)

  • class UndoItem: a unit of the Undo/Redo action
  • class UndoData: encapsulates the containers of UndoItems (undos & redos)

fundo.h:

  1. class UndoPar: Is for Undo/Redo parameters (Data)
  2. class UndoPar (
    public:
       UndoPar();
       UndoPar(const UndoPar& par);
       UndoPar& operator=(const UndPar& par);
    
       // rewind current parameter position
       void Rewind() {it_ = buffer_.begin(); }
    
       template <typename T> void AddPar( T par );
       template <typename T> T    GetPar();
    
    private:
       std::vector<char> buf_;               // parameters buffer
       std::vector<char>::iterator it_;      // current parameter
                                             // position
       static const size_t chunk_sz = 128;   // buffer reallocation
                                             // chunk
    }
    

    Data are stored in the buf_ dynamic container. You may vary the size of the reallocation chunk. By default, I set it to 128 bytes.

    To store the data:

    UndoPar par;
    par.Rewind();
    par.AddPar<double>(5.);
    par.AddPar<int>(2);
    par.AddPar<short>(2);
    

    To get data back:

    UndoPar par;
    par.Rewind();
    double d = par.GetPar<double>();
    int n    = par.GetPar<int>();
    short s  = par.GetPar<short>();
    

    In fact, you may use more complex structure data types instead of ordinary types.

  3. class UndoTarget: Is a base class for the classes supporting Undo/Redo functionality.
  4. class UndoTarget
    {
       virtual ~UndoTarget() {}
       void fn(bool, UndoPar&);
    }
    typedef (UndoTarget::* pfnType)(bool, UndoPar&);
    
  5. class Ftor: Functor.While applying operator(), the method that performs Undo/Redo is activated.
  6. class Ftor
    {
    public:
       Ftor(UndoTarget* pobj, pfnType pfn) : pobj_(pobj),
           pfn_(pfn) {}
    
       void operator()(bool b, UndoPar& par)
       {
          (pobj_->*pfn_)(b, par);
       }
    
    private:
       UndoTarget* pobj_;
       pfnType     pfn_;
    }
    
  7. class UndoRedo: Encapsulates functor to be activated while doing Undo/Redo, and the data to be applied.
  8. class UndoRedo
    {
    public:
       UndoRedo(Ftor& ftor, UndoPar& par) :
                ftor_(ftor), undopar_(par) {}
       void Undo() {ftor_( false, undopar_ );}
       void Redo() {ftor_( true, undopar_ );}
    private:
       Ftor ftor_;
       UndoPar undopar_;    // undo/redo data
    }
    
  9. class AppUndos: This class is in charge of Undo/Redo at the application level.
  10. class AppUndos : public UndoData<UndoRedo>
    {
    public:
       explicit AppUndos(size_t nMaxUndos = MAX_UNDOS) :
          UndoData<UndoRedo>(nMaxUndos) {}
    
       void AddUndoItem(UndoRedo& f)
       {
          UndoData<UndoRedo>::AddUndoItem( UndoAction(f) );
       }
    }
    

    Note that MAX_UNDOS may be any reasonable value.

  11. The files AppData.[h,cpp] are the example of the usage of the foregoing classes. They implement the Data class.
  12. class Data : public UndoTarget
    {
    public:
       Data();
       ~Data() {};
    
       void f1();
       void f2();
    
       void Dump( const char* ) const;
    
       void Undo() { m_undo.UndoLastAction(); }
       void Redo() { m_undo.RedoLastUndo(); }
    
    private:
    
       // signature of f1_ & f2_ must comply pfnType
       void f1_( bool, UndoPar& );    // false: undo, true: redo
       void f2_( bool, UndoPar& );
    
       std::vector<double> m_x;
       AppUndos                  m_undo;
    };
    

Suppose our application can execute f1() on the array of the double data, m_x, X = a*(b*X+c)

void Data::f1()
{
   UndoPar par;
   par.Rewind();
   par.AddPar<double>(5.);    // b
   par.AddPar<int>(2);        // a
   par.AddPar<short>(2);      // c

   f1_(true, par);

   UndoRedo ur( Ftor(this, (pfnType)f1_), par );
   m_undo.AddUndoItem( ur ); 
}

f1_() is called:

  1. Directly to make caculations.
  2. Indirectly (functor is activated) when doing Undo() or Redo().

Installation

Project MyUndo0

Unzip the source code that is supplied. The EXE file is already in the Release folder.

Project MyUndo

This uses Alexandrescu's generalized functors, [2]. You should have the Loki library ([3]) installed. Project Directories Properties assumes that the MyUndo folder is at the same level with Loki Level. SmallObj.cpp is already in the MyUndo folder and includes the "stdafx.h" header.

The test is the Win32 console application. Initially, an array of double values is: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

Function f1 makes X = 2*(5.*X + 2)
Function f2 makes X = 2.45*x + 1

The following sequence is applied:

f1();
f2();
Undo();
Undo();
Redo();
Redo();
Undo();
Undo();

Each data modification is followed by dumping the current values on the console. Logically, with such a sequence applied, we should end up with values equal to those before the calculations.

Conclusion

The presented functorized Undo/Redo classes are really helpful because:

  1. They are portable because they're made on pure C++.
  2. Their application may vary: data processing, text editors ... (due to a dynamic undo-data buffer allocation that is able to store information of any kind).

References

  1. Dr. Dobb's Journal, November 1998
  2. Alexandrescu, Andrei. Modern C++ Design: Generic Programming and Design Patterns Applied. Addison-Wesley, 2001
  3. Loki's library source code: http://www.awl.com/cseng/titles/0-201-70431-5


Downloads

Comments

  • That Is The Best Herbal Male Augmentation or Erectile Dysfunction Product?

    Posted by apeeffifielm on 06/21/2013 06:31am

    Do Home Erectile Dysfunction Pills Bring About Stronger And Rock Hard Erection? a condition in which an erection lasts for longer than 4 hours [url=http://rxhealth.pw ] viagra women depression [/url] see additional Erectile Dysfunction: - Signs And Symptoms, Causes and Treatment

    Reply
  • http://www.oakleysunglassesoutc.com/ yutewa

    Posted by http://www.oakleysunglassesoutc.com/ Mandyoiq on 03/29/2013 05:44am

    ghd hair straightener,Shanghai is bounded by the northern markets for Huasheng, the South by respect for arrived sheep. Huasheng Textile Factory with a cotton textile mills are arrived sheep provided, although this is Li Hongzhang had to dredge Tan Zhonglin made concessions, but also Sheng Xuanhuai want to focus Exhibition weaving industry due. Reduce the cost of reconstruction wasted. Cotton yarn and market allocation. Although the two failed to reach agreements for what on paper, but they act in harmony designated as the boundary interfere with each other, because of the soaring price of cotton yarn to. Arrived in sheep to Huasheng production also lower than the market price. Two has thousands of silk Wan hunchback contact Sheng Xuanhuai, and Tan Yankai the two terms of ghd hair straightener has as landlord to invite each other and to accept each other as guests invited places obligations. The Sheng Xuanhuai home is in the outskirts of a yard, outside the Park within the luxury country house, and Li, Sheng prefer Westernization - unless ghd To see Li and other identity is much higher than the ghd straightener , or ghd sale wearing suits and ties.

    Reply
  • http://www.tomsoutletw.com/ vejqvr

    Posted by http://www.tomsoutletw.com/ Suttonykw on 03/28/2013 02:27pm

    http://www.oakleysunglassesoutc.com/ Ning Caihua this time already Pie Zhuozui his eyes looked with envy still Su drizzle arms hematemesis stay silly, beautiful girls so concerned with the ray ban clubmaster, I am afraid that is also willing to spit oakley sunglasses a blood test. Xiao Feng heard the drizzle words Su and did not say anything, just the blood ejected by the left hand facing the ground Wei Dabao trick, that the blood have blown oakley sunglasses discount in the hands of the formation of a blood cell. Then cheap oakley sunglasses used his right hand whither point in the blood cells, and then even try with their tongues that blood. ray ban glasses the strange performance let ray ban aviators people face to face and peep ray ban aviators do not know in the end want to do. No wonder ... but a little pity. Looked at of Xiao Feng shook his head and looked at that group of their own hands, Wei Dabao just spit blood, and this time everyone even if do not know ray ban aviators specifically just what, but also be able to guess ray ban aviators necessarily Wei Dabao blood in is something, perhaps the thing that makes the big treasure Wei as odd habit.

    Reply
  • cheap ugg boots xLoa wAub

    Posted by Suttongpc on 03/09/2013 11:44am

    cheap nike air max 90 gjwfvnjm cheap nike air max esznmlxu nike air max 1 qkaqpebt nike air max 90 kjtmsxnp nike air max 95 rprirdlg nike air max pusbemnp nike free run ryialojg nike store uk saohctbz nike uk anuqwljt

    Reply
  • ghd australia dlisnk

    Posted by Mandygxn on 02/07/2013 10:45am

    0tNly ugg jWul xErn nike shox sko 4dEgk toms outlet 4lZah hollister 4tGol ugg 2sGwh longchamps 9rKkv louis vuitton outlet 5uYfw michael kors outlet 9zXvz christian louboutin 4rNna Anthony Davis Jersey 9iCag 4vUcx 2oVzz ghd 4lMit cheap uggs

    Reply
  • http://frzzbottespascher.webnode.fr/ mfzqor odrwuh

    Posted by PambInabe on 11/18/2012 10:15am

    mephz vseiw bottes genre ugg ugg paris bottes ugg soldes avis tynsw rcfqle Functorized Undo/Redo jcepzih bottes ugg new york bottes ugg bottes ugg plumdale rjycryl jpjdw ダウンジャケット モンクレール レディース モンクレール 2012 レディースモンクレール raabbksn モンクレールのダウンジャケット モンクレール 2012 モンクレール レディース ikbkiubt

    Reply
  • vyqsntin rimjcqyy tymhe http://sacvuittonnpascher.webnode.fr/

    Posted by felmfeelpbaxy on 11/17/2012 01:14pm

    hhpkb yxeqj abercrombie sdupp aadoni Functorized Undo/Redo lgrbxnp abercrombie paris dzvrjrh eksxk sac louis vuitton pas cher pxamtuwb sac louis vuitton pas cher vcuggsdk louboutin jxbqnvzf

    Reply
  • cggtdojq nwoukvys http://abercromfitchzpascher.webnode.fr/ ujpnjcpa bhlsrr

    Posted by rootlyJerie on 11/16/2012 11:32pm

    qanmio jzcocf moncler doudoune dvylgfqh doudoune moncler hxakvxm furfqnd sxshi Functorized Undo/Redo hpbsgle timberland sale bpngjmjo ghd outlet uk ivlbikat moncler paris zzcipxdt

    Reply
  • christian louboutin shoes burlesque

    Posted by boowiffRodial on 11/14/2012 04:53am

    Functorized Undo/Redo psgjrh eqxoonh vdqgmf coach outlet williamsburg coach purses coach handbags ebay fake rfzwmna zehztkap christian louboutin shoes online cheap christian louboutin christianlouboutinoutlet.net okhvfhu moxna オーストラリア ugg ugg ブーツ ugg 正規品 xquwvjnw moncler japan モンクレール ダウン moncler beams zvxurhrd

    Reply
  • christian louboutin shoes uk online

    Posted by Ralclabycer on 11/12/2012 09:26pm

    Functorized Undo/Redo ltvfck zvbzzaw btlkej christian louboutin shoes edinburgh christian louboutin cheap christian louboutin outlet vegas kkgxqzf iohnkcbf ugg outlet vaughan mills ugg boots ugg boots ebay size 10 fkyzohf xghxh louis vuitton handbags vintage louis vuitton bags louis vuitton outlet locations in new jersey etxljdxr beats by dre yelawolf cheap beats cheap beats by dre monster yrvtykqb

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

  • When it comes to desktops – physical or virtual – it's all about the applications. Cloud-hosted virtual desktops are growing fast because you get local data center-class security and 24x7 access with the complete personalization and flexibility of your own desktop. Organizations make five common mistakes when it comes to planning and implementing their application management strategy. This eBook tells you what they are and how to avoid them, and offers real-life case studies on customers who didn't …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds