Merged with trunk R1612.
[ardour.git] / libs / pbd / pbd / memento_command.h
1 /* 
2    Copyright (C) 2006 Hans Fugal & Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __lib_pbd_memento_command_h__
21 #define __lib_pbd_memento_command_h__
22
23 #include <iostream>
24 using std::cerr;
25 using std::endl;
26
27 #include <pbd/command.h>
28 #include <pbd/stacktrace.h>
29 #include <pbd/xml++.h>
30 #include <pbd/shiva.h>
31
32 #include <sigc++/slot.h>
33 #include <typeinfo>
34
35 /** This command class is initialized with before and after mementos 
36  * (from Stateful::get_state()), so undo becomes restoring the before
37  * memento, and redo is restoring the after memento.
38  */
39
40 template <class obj_T>
41 class MementoCommand : public Command
42 {
43     public:
44         MementoCommand(obj_T &object, 
45                        XMLNode *before,
46                        XMLNode *after
47                        ) 
48             : obj(object), before(before), after(after) {
49                 /* catch destruction of the object */
50                 new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this);
51         }
52
53         ~MementoCommand () {
54                 GoingAway();
55                 if (before) {
56                         delete before;
57                 }
58                 if (after) {
59                         delete after;
60                 }
61         }
62         void operator() () 
63         {
64             if (after)
65                 obj.set_state(*after); 
66         }
67         void undo() 
68         { 
69             if (before)
70                 obj.set_state(*before); 
71         }
72         virtual XMLNode &get_state() 
73         {
74             string name;
75             if (before && after)
76                 name = "MementoCommand";
77             else if (before)
78                 name = "MementoUndoCommand";
79             else
80                 name = "MementoRedoCommand";
81
82             
83             XMLNode *node = new XMLNode(name);
84
85             node->add_property("obj_id", obj.id().to_s());
86             node->add_property("type_name", typeid(obj).name());
87             
88             if (before)
89                     node->add_child_copy(*before);
90             if (after)
91                     node->add_child_copy(*after);
92
93             return *node;
94         }
95
96     protected:
97         obj_T &obj;
98         XMLNode *before, *after;
99 };
100
101 #endif // __lib_pbd_memento_h__