GenericPluginUI: tweak MIDI patch select layout
[ardour.git] / libs / pbd / stateful_diff_command.cc
index bfd9f3344071a422c422bc3a08e94faa3673f0c0..e3a65ffc12c69f5551c5d10fc9d7353ffd199056 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2010 Paul Davis 
+    Copyright (C) 2010 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 */
 
-#include <iostream>
-
 #include "pbd/stateful_diff_command.h"
+#include "pbd/types_convert.h"
 #include "pbd/property_list.h"
 #include "pbd/demangle.h"
-#include "i18n.h"
+#include "pbd/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 (boost::shared_ptr<Stateful> s)
-       : _object (s)
-        , _before (new PropertyList)
-        , _after (new PropertyList)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
+        : _object (s)
+        , _changes (0)
 {
-        s->diff (*_before, *_after);
+       _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<Stateful> s, XMLNode const & n)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
        : _object (s)
-        , _before (0)
-        , _after (0)
+        , _changes (0)
 {
         const XMLNodeList& children (n.children());
 
         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
-                if ((*i)->name() == X_("Undo")) {
-                        _before = s->property_factory (**i);
-                } else if ((*i)->name() == X_("Do")) {
-                        _after = s->property_factory (**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.
+        */
 
-        assert (_before != 0);
-        assert (_after != 0);
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
 }
 
 StatefulDiffCommand::~StatefulDiffCommand ()
 {
-        delete _before;
-        delete _after;
+        drop_references ();
+
+        delete _changes;
 }
 
 void
@@ -71,10 +78,7 @@ StatefulDiffCommand::operator() ()
        boost::shared_ptr<Stateful> s (_object.lock());
 
        if (s) {
-                PropertyChange changed = s->set_properties (*_after);
-                if (!changed.empty()) {
-                        s->PropertyChanged (changed);
-                }
+                s->apply_changes (*_changes);
        }
 }
 
@@ -84,12 +88,9 @@ StatefulDiffCommand::undo ()
        boost::shared_ptr<Stateful> s (_object.lock());
 
        if (s) {
-                std::cerr << "Undoing a stateful diff command\n";
-                PropertyChange changed = s->set_properties (*_before);
-                if (!changed.empty()) {
-                        std::cerr << "Sending changed\n";
-                        s->PropertyChanged (changed);
-                }
+               PropertyList p = *_changes;
+               p.invert ();
+                s->apply_changes (p);
        }
 }
 
@@ -105,17 +106,20 @@ StatefulDiffCommand::get_state ()
 
        XMLNode* node = new XMLNode (X_("StatefulDiffCommand"));
 
-       node->add_property ("obj-id", s->id().to_s());
-       node->add_property ("type-name", demangled_name (*s.get()));
+       node->set_property ("obj-id", s->id());
+       node->set_property ("type-name", demangled_name (*s.get()));
+
+        XMLNode* changes = new XMLNode (X_("Changes"));
 
-        XMLNode* before = new XMLNode (X_("Undo"));
-        XMLNode* after = new XMLNode (X_("Do"));
+        _changes->get_changes_as_xml (changes);
 
-        _before->add_history_state (before);
-        _after->add_history_state (after);
-        
-        node->add_child_nocopy (*before);
-        node->add_child_nocopy (*after);
+        node->add_child_nocopy (*changes);
 
        return *node;
 }
+
+bool
+StatefulDiffCommand::empty () const
+{
+       return _changes->empty();
+}