summaryrefslogtreecommitdiff
path: root/libs/pbd
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2012-06-16 17:20:10 +0000
committerCarl Hetherington <carl@carlh.net>2012-06-16 17:20:10 +0000
commit5ac22e9095d5f851b5238029e3f813bc86fe2280 (patch)
tree51460c63aa9ace692dedceb01494f2a92d4bc364 /libs/pbd
parent9429401f11ffa0ee1729dbdc5e14e87cf06e2dc1 (diff)
Add new SharedStatefulProperty which manages a shared_ptr to
some Stateful object, and a subclass to use this for AutomationList. SharedStatefulProperty will manage undo / redo using full copies of the XML state, like MementoCommand, but does it within the Property undo system. git-svn-id: svn://localhost/ardour2/branches/3.0@12740 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd')
-rw-r--r--libs/pbd/pbd/properties.h115
-rw-r--r--libs/pbd/xml++.cc22
2 files changed, 129 insertions, 8 deletions
diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h
index d961046760..e65929c60c 100644
--- a/libs/pbd/pbd/properties.h
+++ b/libs/pbd/pbd/properties.h
@@ -30,6 +30,7 @@
#include "pbd/property_basics.h"
#include "pbd/property_list.h"
#include "pbd/enumwriter.h"
+#include "pbd/stateful.h"
namespace PBD {
@@ -341,7 +342,121 @@ private:
/* no copy-construction */
EnumProperty (EnumProperty const &);
};
+
+/** A Property which holds a shared_ptr to a Stateful object,
+ * and handles undo using the somewhat inefficient approach
+ * of saving the complete XML state of its object before and
+ * after changes. A sort of half-way house between the old
+ * complete-state undo system and the new difference-based
+ * one.
+ */
+template <class T>
+class SharedStatefulProperty : public PropertyBase
+{
+public:
+ typedef boost::shared_ptr<T> Ptr;
+ SharedStatefulProperty (PropertyID d, Ptr p)
+ : PropertyBase (d)
+ , _current (p)
+ {
+
+ }
+
+ SharedStatefulProperty (PropertyID d, Ptr o, Ptr c)
+ : PropertyBase (d)
+ , _old (o)
+ , _current (c)
+ {
+
+ }
+
+ bool set_value (XMLNode const & node) {
+
+ /* Look for our node */
+ XMLNode* n = node.child (property_name ());
+ if (!n) {
+ return false;
+ }
+
+ /* And there should be one child which is the state of our T */
+ XMLNodeList const & children = n->children ();
+ if (children.size() != 1) {
+ return false;
+ }
+
+ _current->set_state (*children.front (), Stateful::current_state_version);
+ return true;
+ }
+
+ void get_value (XMLNode & node) const {
+ XMLNode* n = node.add_child (property_name ());
+ n->add_child_nocopy (_current->get_state ());
+ }
+
+ void clear_changes () {
+ /* We are starting to change things, so _old gets set up
+ with the current state.
+ */
+ _old.reset (new T (*_current.get()));
+ }
+
+ bool changed () const {
+ /* Expensive, but, hey; this requires operator!= in
+ our T
+ */
+ return (*_old != *_current);
+ }
+
+ void invert () {
+ _current.swap (_old);
+ }
+
+ void get_changes_as_xml (XMLNode* history_node) const {
+ /* We express the diff as before and after state, just
+ as MementoCommand does.
+ */
+ XMLNode* p = history_node->add_child (property_name ());
+ XMLNode* from = p->add_child ("from");
+ from->add_child_nocopy (_old->get_state ());
+ XMLNode* to = p->add_child ("to");
+ to->add_child_nocopy (_current->get_state ());
+ }
+
+ void get_changes_as_properties (PropertyList& changes, Command *) const {
+ if (changed ()) {
+ changes.add (clone ());
+ }
+ }
+
+ void apply_changes (PropertyBase const * p) {
+ *_current = *(dynamic_cast<SharedStatefulProperty const *> (p))->val ();
+ }
+
+ Ptr val () const {
+ return _current;
+ }
+
+ T* operator-> () const {
+ return _current.operator-> ();
+ }
+
+ operator bool () const {
+ return _current;
+ }
+
+protected:
+
+ Ptr _old;
+ Ptr _current;
+
+private:
+
+ /* No copy-construction nor assignment */
+ SharedStatefulProperty (SharedStatefulProperty<T> const &);
+ SharedStatefulProperty<T>& operator= (SharedStatefulProperty<T> const &);
+};
+
} /* namespace PBD */
#include "pbd/property_list_impl.h"
diff --git a/libs/pbd/xml++.cc b/libs/pbd/xml++.cc
index e2ccd67738..3046f971ab 100644
--- a/libs/pbd/xml++.cc
+++ b/libs/pbd/xml++.cc
@@ -652,13 +652,19 @@ static XMLSharedNodeList* find_impl(xmlXPathContext* ctxt, const string& xpath)
void
XMLNode::dump (ostream& s, string p) const
{
- s << p << _name << " ";
- for (XMLPropertyList::const_iterator i = _proplist.begin(); i != _proplist.end(); ++i) {
- s << (*i)->name() << "=" << (*i)->value() << " ";
- }
- s << "\n";
-
- for (XMLNodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) {
- (*i)->dump (s, p + " ");
+ if (_is_content) {
+ s << p << " " << content() << "\n";
+ } else {
+ s << p << "<" << _name;
+ for (XMLPropertyList::const_iterator i = _proplist.begin(); i != _proplist.end(); ++i) {
+ s << " " << (*i)->name() << "=\"" << (*i)->value() << "\"";
+ }
+ s << ">\n";
+
+ for (XMLNodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) {
+ (*i)->dump (s, p + " ");
+ }
+
+ s << p << "</" << _name << ">\n";
}
}