00001 #include "Undoable.h"
00002 #include <sigc++/bind.h>
00003 #include <sigc++/object_slot.h>
00004
00005 class UndoableInt : public Undoable
00006 {
00007 public:
00008 UndoableInt(int i) : fVal(i) {}
00009 virtual ~UndoableInt() {}
00010 void Set(int i) { fVal = i; }
00011 int Get(void) { return fVal; }
00012
00013
00014 UndoMemento GetMemento(void)
00015 { return SigC::bind(SigC::slot(this,&UndoableInt::Set),fVal); }
00016 private:
00017 int fVal;
00018 };
00019
00020 class BigUndoable : public Undoable
00021 {
00022
00023 public:
00024
00025 struct MyState {
00026 int fInt;
00027 float fFloat;
00028 MyState(int i, float f) : fInt(i), fFloat(f) {};
00029 MyState() : fInt(0), fFloat(0.0) {};
00030 };
00031
00032 BigUndoable(int i, float f) {fState.fInt = i; fState.fFloat = f;}
00033 ~BigUndoable() {}
00034
00035 void SetState(MyState ms) { fState = ms; }
00036 int GetInt() { return fState.fInt; }
00037 float GetFloat() { return fState.fFloat; }
00038 void IncState() { ++fState.fInt; ++fState.fFloat; }
00039
00040 UndoMemento GetMemento(void)
00041 { return SigC::bind(SigC::slot(this,&BigUndoable::SetState),fState); }
00042
00043 private:
00044 MyState fState;
00045 };
00046 int test1()
00047 {
00048 UndoableInt i1(42);
00049 UndoHistory uh;
00050 UndoableInt i2(69), i3(1);
00051 BigUndoable bu(0,0.0);
00052
00053
00054 for (int i=0; i<5; ++i) {
00055 UndoCommand uc;
00056
00057 uc.push_back(UndoItem(i1));
00058 uc.push_back(UndoItem(i2));
00059 uh.Store(uc);
00060 assert(uc.size() == 0);
00061
00062 uc.push_back(UndoItem(i3));
00063 uh.Store(uc);
00064 assert(uc.size() == 0);
00065
00066 uc.push_back(UndoItem(bu));
00067 uh.Store(uc);
00068 assert(uc.size() == 0);
00069
00070 cerr << "[" << i << "] "
00071 << "Stored as "
00072 << "[i1=" << i1.Get()
00073 << ", i2=" << i2.Get()
00074 << "], [i3=" << i3.Get() << "], ("
00075 << bu.GetInt() << "," << bu.GetFloat() <<") ";
00076 i1.Set(i1.Get()+1);
00077 i2.Set(i2.Get()+1);
00078 i3.Set(i3.Get()+1);
00079 bu.IncState();
00080 cerr << "modify to "
00081 << "[i1=" << i1.Get()
00082 << ", i2=" << i2.Get()
00083 << "], [i3=" << i3.Get()
00084 << "], ("
00085 << bu.GetInt() << "," << bu.GetFloat() <<") " << endl;
00086 }
00087
00088 cerr << endl;
00089
00090
00091 for (int i=0; i<16; ++i) {
00092 cerr << "[undo #" << i << "] "
00093 << "i1=" << i1.Get()
00094 << ", i2=" << i2.Get()
00095 << ", i3=" << i3.Get()
00096 << " (" << bu.GetInt() << "," << bu.GetFloat() <<") ";
00097 if (uh.Undo())
00098 cerr << " after: "
00099 << "i1=" << i1.Get()
00100 << ", i2=" << i2.Get()
00101 << ", i3=" << i3.Get()
00102 << " (" << bu.GetInt() << "," << bu.GetFloat() <<") "
00103 << endl;
00104 else
00105 cerr << " Nothing to undo\n";
00106 }
00107
00108 cerr << endl;
00109
00110
00111 for (int i=0; i<16; ++i) {
00112 cerr << "[redo #" << i << "] "
00113 << "i1=" << i1.Get()
00114 << ", i2=" << i2.Get()
00115 << ", i3=" << i3.Get()
00116 << " (" << bu.GetInt() << "," << bu.GetFloat() <<") ";
00117 if (uh.Redo())
00118 cerr << " after: "
00119 << "i1=" << i1.Get()
00120 << ", i2=" << i2.Get()
00121 << ", i3=" << i3.Get()
00122 << " (" << bu.GetInt() << "," << bu.GetFloat() <<") "
00123 << endl;
00124 else
00125 cerr << " Nothing to redo\n";
00126 }
00127
00128 return 0;
00129 }
00130
00131 class Composite : public Undoable
00132 {
00133 public:
00134 Composite() : i1(1), i2(2), i3(3) {}
00135 virtual ~Composite() {}
00136
00137
00138 UndoMemento GetMemento(void) {
00139 vector<UndoMemento> umv;
00140 umv.push_back(i1.GetMemento());
00141 umv.push_back(i2.GetMemento());
00142 umv.push_back(i3.GetMemento());
00143 return SigC::bind(SigC::slot(this,&Composite::ProcVec),umv);
00144 }
00145
00146 void ProcVec(vector<UndoMemento> umv) {
00147 vector<UndoMemento>::iterator vit;
00148 for (vit = umv.begin(); vit != umv.end(); ++vit) (*vit)();
00149 }
00150
00151 void Increment() {
00152 i1.Set(i1.Get()+1);
00153 i2.Set(i2.Get()+1);
00154 i3.Set(i3.Get()+1);
00155 }
00156
00157 void Print() {
00158 cout << "i1="<< i1.Get()
00159 << " i2="<< i2.Get()
00160 << " i3="<< i3.Get()
00161 << endl;
00162 }
00163
00164 private:
00165 UndoableInt i1, i2, i3;
00166
00167 };
00168
00169 int test2()
00170 {
00171 Composite c;
00172 UndoHistory uh;
00173
00174
00175 for (int i=0; i<5; ++i) {
00176 UndoCommand uc;
00177
00178 uc.push_back(UndoItem(c));
00179 uh.Store(uc);
00180 assert(uc.size() == 0);
00181
00182 cout << "Before: "; c.Print();
00183 c.Increment();
00184 cout << "After: "; c.Print();
00185
00186 }
00187
00188 cout << endl;
00189
00190
00191 for (int i=0; i<6; ++i) {
00192 cout << "Before undo: "; c.Print();
00193 if (uh.Undo()) {
00194 cout << "After undo: "; c.Print();
00195 }
00196 else
00197 cout << "Nothing to undo\n";
00198 }
00199
00200 cerr << endl;
00201
00202
00203 for (int i=0; i<6; ++i) {
00204 cout << "Before redo: "; c.Print();
00205 if (uh.Redo()) {
00206 cout << "After redo: "; c.Print();
00207 }
00208 else
00209 cout << "Nothing to redo\n";
00210 }
00211
00212 return 0;
00213 }
00214
00215 int main (int argc, char *argv[])
00216 {
00217 char c = '1';
00218 if (argc > 1) c = argv[1][0];
00219 switch (c) {
00220 case '1':
00221 return test1();
00222 break;
00223 case '2':
00224 default:
00225 return test2();
00226 break;
00227 }
00228 return 0;
00229 }