diff options
Diffstat (limited to 'libs/pbd/pbd/properties.h')
-rw-r--r-- | libs/pbd/pbd/properties.h | 199 |
1 files changed, 58 insertions, 141 deletions
diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h index 1c3519766f..274dfffd9c 100644 --- a/libs/pbd/pbd/properties.h +++ b/libs/pbd/pbd/properties.h @@ -27,96 +27,19 @@ #include <glib.h> #include "pbd/xml++.h" +#include "pbd/property_basics.h" +#include "pbd/property_list.h" namespace PBD { -typedef GQuark PropertyID; - -template<typename T> -struct PropertyDescriptor { - PropertyID id; - typedef T value_type; -}; - -class PropertyChange : public std::set<PropertyID> -{ -public: - PropertyChange() {} - - template<typename T> - PropertyChange(PropertyDescriptor<T> p) { insert (p.id); } - - PropertyChange(const PropertyChange& other) : std::set<PropertyID> (other) {} - - PropertyChange operator=(const PropertyChange& other) { - clear (); - insert (other.begin (), other.end ()); - return *this; - } - - template<typename T> - PropertyChange operator=(PropertyDescriptor<T> p) { - clear (); - insert (p.id); - return *this; - } - - template<typename T> - bool contains (PropertyDescriptor<T> p) const { return find (p.id) != end (); } - - bool contains (const PropertyChange& other) const { - for (const_iterator x = other.begin (); x != other.end (); ++x) { - if (find (*x) != end ()) { - return true; - } - } - return false; - } - - void add (PropertyID id) { (void) insert (id); } - void add (const PropertyChange& other) { (void) insert (other.begin (), other.end ()); } - template<typename T> - void add (PropertyDescriptor<T> p) { (void)insert (p.id); } -}; - -/** Base (non template) part of Property */ -class PropertyBase -{ -public: - PropertyBase (PropertyID pid) - : _property_id (pid) - , _have_old (false) - {} - - /** Forget about any old value for this state */ - void clear_history () { - _have_old = false; - } - - virtual void diff (XMLNode*, XMLNode*) const = 0; - virtual void diff (PropertyChange&) const = 0; - virtual bool set_state (XMLNode const&) = 0; - virtual void add_state (XMLNode&) const = 0; - - const gchar*property_name () const { return g_quark_to_string (_property_id); } - PropertyID id () const { return _property_id; } - - bool operator==(PropertyID pid) const { - return _property_id == pid; - } - -protected: - PropertyID _property_id; - bool _have_old; -}; - -/** Parent class for classes which represent a single property in a Stateful object */ +/** Parent class for classes which represent a single scalar property in a Stateful object + */ template<class T> class PropertyTemplate : public PropertyBase { public: PropertyTemplate (PropertyDescriptor<T> p, T const& v) - : PropertyBase (p.id) + : PropertyBase (p.property_id) , _current (v) {} @@ -156,25 +79,22 @@ public: return _current; } - void diff (XMLNode* old, XMLNode* current) const { - if (_have_old) { - old->add_property (property_name (), to_string (_old)); - current->add_property (property_name (), to_string (_current)); - } - } - - void diff (PropertyChange& c) const { - if (_have_old) { - c.add (_property_id); - } + /** If this property has been changed since the last clear_history() call + (or its construction), add an (XML) property describing the old value + to the XMLNode @param old and another describing the current value to + the XMLNode @param current. + */ + void add_history_state (XMLNode* history_node) const { + history_node->add_property (property_name(), to_string (_current)); } /** Try to set state from the property of an XML node. * @param node XML node. * @return true if the value of the property is changed */ - bool set_state (XMLNode const& node) { - XMLProperty const* p = node.property (property_name ()); + bool set_state_from_owner_state (XMLNode const& owner_state) { + + XMLProperty const* p = owner_state.property (property_name()); if (p) { T const v = from_string (p->value ()); @@ -188,11 +108,19 @@ public: return false; } - void add_state (XMLNode& node) const { - node.add_property (property_name (), to_string (_current)); + void add_state_to_owner_state (XMLNode& owner_state) const { + owner_state.add_property (property_name(), to_string (_current)); } protected: + /** Constructs a PropertyTemplate with a default + value for _old and _current. + */ + + PropertyTemplate (PropertyDescriptor<T> p) + : PropertyBase (p.property_id) + {} + void set (T const& v) { _old = _current; _have_old = true; @@ -212,7 +140,7 @@ std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s) return os << s.val (); } -/** Representation of a single piece of state in a Stateful; for use +/** Representation of a single piece of scalar state in a Stateful; for use * with types that can be written to / read from stringstreams. */ template<class T> @@ -222,6 +150,21 @@ public: Property (PropertyDescriptor<T> q, T const& v) : PropertyTemplate<T> (q, v) {} + + void diff (PropertyList& before, PropertyList& after) const { + if (this->_have_old) { + before.add (new Property<T> (this->property_id(), this->_old)); + after.add (new Property<T> (this->property_id(), this->_current)); + } + } + + Property<T>* maybe_clone_self_if_found_in_history_node (const XMLNode& node) const { + const XMLProperty* prop = node.property (this->property_name()); + if (!prop) { + return 0; + } + return new Property<T> (this->property_id(), from_string (prop->value())); + } T & operator=(T const& v) { this->set (v); @@ -229,6 +172,12 @@ public: } private: + friend class PropertyFactory; + + Property (PropertyDescriptor<T> q) + : PropertyTemplate<T> (q) + {} + /* Note that we do not set a locale for the streams used * in to_string() or from_string(), because we want the * format to be portable across locales (i.e. C or @@ -254,7 +203,7 @@ private: /** Specialization, for std::string which is common and special (see to_string() and from_string() * Using stringstream to read from a std::string is easy to get wrong because of whitespace - * delineation, etc. + * separators, etc. */ template<> class Property<std::string> : public PropertyTemplate<std::string> @@ -264,6 +213,13 @@ public: : PropertyTemplate<std::string> (q, v) {} + void diff (PropertyList& before, PropertyList& after) const { + if (this->_have_old) { + before.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_old)); + after.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_current)); + } + } + std::string & operator=(std::string const& v) { this->set (v); return this->_current; @@ -280,48 +236,9 @@ private: }; -class PropertyList : public std::map<PropertyID, PropertyBase*> -{ -public: - PropertyList() : _property_owner (true) {} - virtual ~PropertyList() { - if (_property_owner) { - for (std::map<PropertyID, PropertyBase*>::iterator i = begin (); i != end (); ++i) { - delete i->second; - } - } - } - - /* Classes that own property lists use this to add their - * property members to their plists. - */ - bool add (PropertyBase& p) { - return insert (value_type (p.id (), &p)).second; - } - - /* Code that is constructing a property list for use - * in setting the state of an object uses this. - */ - template<typename T, typename V> - bool add (PropertyDescriptor<T> pid, const V& v) { - return insert (value_type (pid.id, new Property<T> (pid, (T)v))).second; - } - -protected: - bool _property_owner; -}; - -/** A variant of PropertyList that does not delete its - * property list in its destructor. Objects with their - * own Properties store them in an OwnedPropertyList - * to avoid having them deleted at the wrong time. - */ -class OwnedPropertyList : public PropertyList -{ -public: - OwnedPropertyList() { _property_owner = false; } -}; - } /* namespace PBD */ +#include "pbd/property_list_impl.h" +#include "pbd/property_basics_impl.h" + #endif /* __pbd_properties_h__ */ |