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