summaryrefslogtreecommitdiff
path: root/libs/pbd/pbd/properties.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/pbd/pbd/properties.h')
-rw-r--r--libs/pbd/pbd/properties.h116
1 files changed, 82 insertions, 34 deletions
diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h
index 10c661102d..931b2676bd 100644
--- a/libs/pbd/pbd/properties.h
+++ b/libs/pbd/pbd/properties.h
@@ -23,18 +23,13 @@
#include <string>
#include <sstream>
#include <list>
+#include <set>
#include <glib.h>
#include "pbd/xml++.h"
namespace PBD {
-enum PropertyChange {
- range_guarantee = ~0ULL
-};
-
-PropertyChange new_change ();
-
typedef GQuark PropertyID;
template<typename T>
@@ -43,14 +38,48 @@ struct PropertyDescriptor {
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, PropertyChange c)
+ PropertyBase (PropertyID pid)
: _have_old (false)
, _property_id (pid)
- , _change (c)
{
}
@@ -62,11 +91,10 @@ public:
virtual void diff (XMLNode *, XMLNode *) const = 0;
virtual void diff (PropertyChange&) const = 0;
- virtual PropertyChange set_state (XMLNode 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); }
- PropertyChange change() const { return _change; }
PropertyID id() const { return _property_id; }
bool operator== (PropertyID pid) const {
@@ -76,7 +104,6 @@ public:
protected:
bool _have_old;
PropertyID _property_id;
- PropertyChange _change;
};
/** Parent class for classes which represent a single property in a Stateful object */
@@ -84,8 +111,8 @@ template <class T>
class PropertyTemplate : public PropertyBase
{
public:
- PropertyTemplate (PropertyDescriptor<T> p, PropertyChange c, T const & v)
- : PropertyBase (p.id, c)
+ PropertyTemplate (PropertyDescriptor<T> p, T const & v)
+ : PropertyBase (p.id)
, _current (v)
{
@@ -94,7 +121,6 @@ public:
/* XXX: isn't there a nicer place to do this? */
_have_old = s._have_old;
_property_id = s._property_id;
- _change = s._change;
_current = s._current;
_old = s._old;
@@ -129,39 +155,38 @@ public:
void diff (XMLNode* old, XMLNode* current) const {
if (_have_old) {
- old->add_property (g_quark_to_string (_property_id), to_string (_old));
- current->add_property (g_quark_to_string (_property_id), to_string (_current));
+ old->add_property (property_name(), to_string (_old));
+ current->add_property (property_name(), to_string (_current));
}
}
void diff (PropertyChange& c) const {
- if (_have_old && _change) {
- c = PropertyChange (c | _change);
+ if (_have_old) {
+ c.add (_property_id);
}
}
/** Try to set state from the property of an XML node.
* @param node XML node.
- * @return PropertyChange effected, or 0.
+ * @return true if the value of the property is changed
*/
- PropertyChange set_state (XMLNode const & node) {
- XMLProperty const * p = node.property (g_quark_to_string (_property_id));
- PropertyChange c = PropertyChange (0);
+ bool set_state (XMLNode const & node) {
+ XMLProperty const * p = node.property (property_name());
if (p) {
T const v = from_string (p->value ());
if (v != _current) {
set (v);
- c = _change;
+ return true;
}
- }
+ }
- return c;
+ return false;
}
void add_state (XMLNode & node) const {
- node.add_property (g_quark_to_string (_property_id), to_string (_current));
+ node.add_property (property_name(), to_string (_current));
}
protected:
@@ -191,14 +216,8 @@ template <class T>
class Property : public PropertyTemplate<T>
{
public:
- Property (PropertyDescriptor<T> q, PropertyChange c, T const & v)
- : PropertyTemplate<T> (q, c, v)
- {
-
- }
-
Property (PropertyDescriptor<T> q, T const & v)
- : PropertyTemplate<T> (q, PropertyChange (0), v)
+ : PropertyTemplate<T> (q, v)
{
}
@@ -222,7 +241,7 @@ private:
s << v;
return s.str ();
}
-
+
T from_string (std::string const & s) const {
std::stringstream t (s);
T v;
@@ -231,6 +250,35 @@ 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.
+ */
+template <>
+class Property<std::string> : public PropertyTemplate<std::string>
+{
+public:
+ Property (PropertyDescriptor<std::string> q, std::string const & v)
+ : PropertyTemplate<std::string> (q, v)
+ {
+
+ }
+
+ std::string & operator= (std::string const & v) {
+ this->set (v);
+ return this->_current;
+ }
+
+private:
+ std::string to_string (std::string const & v) const {
+ return _current;
+ }
+
+ std::string from_string (std::string const & s) const {
+ return s;
+ }
+};
+
class PropertyList : public std::map<PropertyID,PropertyBase*>
{
public: