Fix typo.
[ardour.git] / libs / pbd / stateful_diff_command.cc
index 788a5be0341776c716f0a9d8fd88e52b212171dc..0f456d2d6e6ac9f042501dd521968bc8f5609fc7 100644 (file)
 
 */
 
+#include <iostream>
+
 #include "pbd/stateful_diff_command.h"
+#include "pbd/property_list.h"
+#include "pbd/demangle.h"
+#include "i18n.h"
 
 using namespace std;
 using namespace PBD;
 
 /** Create a new StatefulDiffCommand by examining the changes made to a Stateful
- *  since the last time that clear_history was called on it.
+ *  since the last time that clear_changes was called on it.
  *  @param s Stateful object.
  */
 
-StatefulDiffCommand::StatefulDiffCommand (Stateful* s)
-       : _object (s)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
+        : _object (s)
+        , _changes (0)
 {
-       pair<XMLNode *, XMLNode*> const p = s->diff ();
-       _before = p.first;
-       _after = p.second;
+       _changes = s->get_changes_as_properties (this);
+
+        /* if the stateful object that this command refers to goes away,
+           be sure to notify owners of this command.
+        */
+
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
 }
 
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
+       : _object (s)
+        , _changes (0)
+{
+        const XMLNodeList& children (n.children());
+
+        for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
+                if ((*i)->name() == X_("Changes")) {
+                        _changes = s->property_factory (**i);
+                }
+       }
+
+        assert (_changes != 0);
+
+        /* if the stateful object that this command refers to goes away,
+           be sure to notify owners of this command.
+        */
+
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
+}
 
 StatefulDiffCommand::~StatefulDiffCommand ()
 {
-       delete _before;
-       delete _after;
+        drop_references ();
+
+        delete _changes;
 }
 
 void
 StatefulDiffCommand::operator() ()
 {
-       _object->set_state (*_after, Stateful::current_state_version);
+       boost::shared_ptr<Stateful> s (_object.lock());
+
+       if (s) {
+                s->apply_changes (*_changes);
+       }
 }
 
 void
 StatefulDiffCommand::undo ()
 {
-       _object->set_state (*_before, Stateful::current_state_version);
+       boost::shared_ptr<Stateful> s (_object.lock());
+
+       if (s) {
+               PropertyList p = *_changes;
+               p.invert ();
+                s->apply_changes (p);
+       }
 }
 
 XMLNode&
 StatefulDiffCommand::get_state ()
 {
-       /* XXX */
+       boost::shared_ptr<Stateful> s (_object.lock());
+
+       if (!s) {
+               /* XXX should we throw? */
+               return * new XMLNode("");
+       }
+
+       XMLNode* node = new XMLNode (X_("StatefulDiffCommand"));
+
+       node->add_property ("obj-id", s->id().to_s());
+       node->add_property ("type-name", demangled_name (*s.get()));
+
+        XMLNode* changes = new XMLNode (X_("Changes"));
+
+        _changes->get_changes_as_xml (changes);
+        
+        node->add_child_nocopy (*changes);
+
+       return *node;
+}
+
+bool
+StatefulDiffCommand::empty () const
+{
+       return _changes->empty();
 }