enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / pbd / stateful_diff_command.cc
1 /*
2     Copyright (C) 2010 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 #include "pbd/stateful_diff_command.h"
21 #include "pbd/property_list.h"
22 #include "pbd/demangle.h"
23 #include "pbd/i18n.h"
24
25 using namespace std;
26 using namespace PBD;
27
28 /** Create a new StatefulDiffCommand by examining the changes made to a Stateful
29  *  since the last time that clear_changes was called on it.
30  *  @param s Stateful object.
31  */
32
33 StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
34         : _object (s)
35         , _changes (0)
36 {
37         _changes = s->get_changes_as_properties (this);
38
39         /* if the stateful object that this command refers to goes away,
40            be sure to notify owners of this command.
41         */
42
43         s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
44 }
45
46 StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
47         : _object (s)
48         , _changes (0)
49 {
50         const XMLNodeList& children (n.children());
51
52         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
53                 if ((*i)->name() == X_("Changes")) {
54                         _changes = s->property_factory (**i);
55                 }
56         }
57
58         assert (_changes != 0);
59
60         /* if the stateful object that this command refers to goes away,
61            be sure to notify owners of this command.
62         */
63
64         s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
65 }
66
67 StatefulDiffCommand::~StatefulDiffCommand ()
68 {
69         drop_references ();
70
71         delete _changes;
72 }
73
74 void
75 StatefulDiffCommand::operator() ()
76 {
77         boost::shared_ptr<Stateful> s (_object.lock());
78
79         if (s) {
80                 s->apply_changes (*_changes);
81         }
82 }
83
84 void
85 StatefulDiffCommand::undo ()
86 {
87         boost::shared_ptr<Stateful> s (_object.lock());
88
89         if (s) {
90                 PropertyList p = *_changes;
91                 p.invert ();
92                 s->apply_changes (p);
93         }
94 }
95
96 XMLNode&
97 StatefulDiffCommand::get_state ()
98 {
99         boost::shared_ptr<Stateful> s (_object.lock());
100
101         if (!s) {
102                 /* XXX should we throw? */
103                 return * new XMLNode("");
104         }
105
106         XMLNode* node = new XMLNode (X_("StatefulDiffCommand"));
107
108         node->add_property ("obj-id", s->id().to_s());
109         node->add_property ("type-name", demangled_name (*s.get()));
110
111         XMLNode* changes = new XMLNode (X_("Changes"));
112
113         _changes->get_changes_as_xml (changes);
114
115         node->add_child_nocopy (*changes);
116
117         return *node;
118 }
119
120 bool
121 StatefulDiffCommand::empty () const
122 {
123         return _changes->empty();
124 }