X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Fpbd%2Fproperties.h;h=70d18db4c7bd74468250b7fefe570bc324593bda;hb=59076a7e4c66db12bbbfbf01f012ca2f6ba4bf56;hp=ad9ed2f1f6a2482afc9f9082a599429b953e7031;hpb=4e62adfe1a8e7b8158204ee6c0d1fe97c3fdca04;p=ardour.git diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h index ad9ed2f1f6..70d18db4c7 100644 --- a/libs/pbd/pbd/properties.h +++ b/libs/pbd/pbd/properties.h @@ -26,17 +26,18 @@ #include #include +#include "pbd/libpbd_visibility.h" #include "pbd/xml++.h" #include "pbd/property_basics.h" #include "pbd/property_list.h" #include "pbd/enumwriter.h" +#include "pbd/stateful.h" namespace PBD { -/** Parent class for classes which represent a single scalar property in a Stateful object - */ +/** Parent class for classes which represent a single scalar property in a Stateful object */ template -class PropertyTemplate : public PropertyBase +class /*LIBPBD_API*/ PropertyTemplate : public PropertyBase { public: PropertyTemplate (PropertyDescriptor p, T const& v) @@ -58,6 +59,9 @@ public: , _current (s._current) {} + + /* OPERATORS / ACCESSORS */ + T & operator=(T const& v) { set (v); return _current; @@ -93,16 +97,9 @@ public: return _current; } - void clear_changes () { - _have_old = false; - } - - void get_changes_as_xml (XMLNode* history_node) const { - XMLNode* node = history_node->add_child (property_name()); - node->add_property ("from", to_string (_old)); - node->add_property ("to", to_string (_current)); - } + /* MANAGEMENT OF Stateful State */ + bool set_value (XMLNode const & node) { XMLProperty const* p = node.property (property_name()); @@ -123,27 +120,46 @@ public: node.add_property (property_name(), to_string (_current)); } - bool changed () const { return _have_old; } - void apply_changes (PropertyBase const * p) { - T v = dynamic_cast* > (p)->val (); - if (v != _current) { - set (v); - } + /* MANAGEMENT OF HISTORY */ + + void clear_changes () { + _have_old = false; } + bool changed () const { return _have_old; } + void invert () { T const tmp = _current; _current = _old; _old = tmp; } + + /* TRANSFERRING HISTORY TO / FROM A StatefulDiffCommand */ + + void get_changes_as_xml (XMLNode* history_node) const { + XMLNode* node = history_node->add_child (property_name()); + node->add_property ("from", to_string (_old)); + node->add_property ("to", to_string (_current)); + } + void get_changes_as_properties (PropertyList& changes, Command *) const { if (this->_have_old) { changes.add (clone ()); } } + + /* VARIOUS */ + + void apply_changes (PropertyBase const * p) { + T v = dynamic_cast* > (p)->val (); + if (v != _current) { + set (v); + } + } + protected: void set (T const& v) { @@ -181,7 +197,7 @@ private: PropertyTemplate (PropertyTemplate const &); }; -template +template /*LIBPBD_API*/ std::ostream & operator<<(std::ostream& os, PropertyTemplate const& s) { return os << s.val (); @@ -191,7 +207,7 @@ std::ostream & operator<<(std::ostream& os, PropertyTemplate const& s) * with types that can be written to / read from stringstreams. */ template -class Property : public PropertyTemplate +class /*LIBPBD_API*/ Property : public PropertyTemplate { public: Property (PropertyDescriptor q, T const& v) @@ -269,7 +285,7 @@ private: * separators, etc. */ template<> -class Property : public PropertyTemplate +class /*LIBPBD_API*/ Property : public PropertyTemplate { public: Property (PropertyDescriptor d, std::string const & v) @@ -303,7 +319,7 @@ private: }; template -class EnumProperty : public Property +class /*LIBPBD_API*/ EnumProperty : public Property { public: EnumProperty (PropertyDescriptor q, T const& v) @@ -327,7 +343,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 /*LIBPBD_API*/ SharedStatefulProperty : public PropertyBase +{ +public: + typedef boost::shared_ptr 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 (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 const &); + SharedStatefulProperty& operator= (SharedStatefulProperty const &); +}; + } /* namespace PBD */ #include "pbd/property_list_impl.h"