diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2010-02-18 13:59:49 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2010-02-18 13:59:49 +0000 |
commit | ce7a5e1c9fa3edf2d9cc66875505e402a0aaa6f6 (patch) | |
tree | 8a798270cd892823c7eeef99c2f3cdd4bf657bb3 /libs/pbd/pbd | |
parent | cdcc4d3720d8168a158f6a5a5f23e9ce981bc68c (diff) |
the Properties & 64bit region commit
git-svn-id: svn://localhost/ardour2/branches/3.0@6695 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/pbd')
-rw-r--r-- | libs/pbd/pbd/properties.h | 121 | ||||
-rw-r--r-- | libs/pbd/pbd/stateful.h | 231 |
2 files changed, 121 insertions, 231 deletions
diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h index 5bab97229c..10c661102d 100644 --- a/libs/pbd/pbd/properties.h +++ b/libs/pbd/pbd/properties.h @@ -21,26 +21,35 @@ #define __pbd_properties_h__ #include <string> +#include <sstream> #include <list> -#include <glib/glib.h> +#include <glib.h> -class XMLNode; +#include "pbd/xml++.h" namespace PBD { enum PropertyChange { - range_guarantee = ~0 + range_guarantee = ~0ULL }; PropertyChange new_change (); +typedef GQuark PropertyID; + +template<typename T> +struct PropertyDescriptor { + PropertyID id; + typedef T value_type; +}; + /** Base (non template) part of Property */ class PropertyBase { public: - PropertyBase (GQuark quark, PropertyChange c) + PropertyBase (PropertyID pid, PropertyChange c) : _have_old (false) - , _property_quark (q) + , _property_id (pid) , _change (c) { @@ -52,19 +61,21 @@ public: } virtual void diff (XMLNode *, XMLNode *) const = 0; + virtual void diff (PropertyChange&) const = 0; virtual PropertyChange set_state (XMLNode const &) = 0; virtual void add_state (XMLNode &) const = 0; - std::string property_name() const { return g_quark_to_string (_property_quark); } + 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== (GQuark q) const { - return _property_quark == q; + bool operator== (PropertyID pid) const { + return _property_id == pid; } protected: bool _have_old; - GQuark _property_quark; + PropertyID _property_id; PropertyChange _change; }; @@ -73,17 +84,16 @@ template <class T> class PropertyTemplate : public PropertyBase { public: - PropertyTemplate (GQuark q, PropertyChange c, T const & v) - : PropertyBase (q, c) + PropertyTemplate (PropertyDescriptor<T> p, PropertyChange c, T const & v) + : PropertyBase (p.id, c) , _current (v) { } - PropertyTemplate<T> & operator= (PropertyTemplate<T> const & s) { /* XXX: isn't there a nicer place to do this? */ _have_old = s._have_old; - _property_quark = s._property_quark; + _property_id = s._property_id; _change = s._change; _current = s._current; @@ -119,8 +129,14 @@ public: void diff (XMLNode* old, XMLNode* current) const { if (_have_old) { - old->add_property (g_quark_to_string (_property_quark), to_string (_old)); - current->add_property (g_quark_to_string (_property_quark), to_string (_current)); + old->add_property (g_quark_to_string (_property_id), to_string (_old)); + current->add_property (g_quark_to_string (_property_id), to_string (_current)); + } + } + + void diff (PropertyChange& c) const { + if (_have_old && _change) { + c = PropertyChange (c | _change); } } @@ -129,24 +145,23 @@ public: * @return PropertyChange effected, or 0. */ PropertyChange set_state (XMLNode const & node) { - XMLProperty const * p = node.property (g_quark_to_string (_property_quark)); + XMLProperty const * p = node.property (g_quark_to_string (_property_id)); + PropertyChange c = PropertyChange (0); if (p) { T const v = from_string (p->value ()); - if (v == _current) { - return PropertyChange (0); + if (v != _current) { + set (v); + c = _change; } - - set (v); - return _change; } - return PropertyChange (0); + return c; } void add_state (XMLNode & node) const { - node.add_property (g_quark_to_string (_property_quark), to_string (_current)); + node.add_property (g_quark_to_string (_property_id), to_string (_current)); } protected: @@ -176,11 +191,17 @@ template <class T> class Property : public PropertyTemplate<T> { public: - Property (GQuark q, PropertyChange c, T const & v) + 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) + { + + } T & operator= (T const & v) { this->set (v); @@ -188,8 +209,14 @@ public: } private: - std::string to_string (T const & v) const { - // XXX LocaleGuard + /* 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 + POSIX). Also, there is the small matter of + std::locale aborting on OS X if used with anything + other than C or POSIX locales. + */ + std::string to_string (T const & v) const { std::stringstream s; s.precision (12); // in case its floating point s << v; @@ -197,15 +224,53 @@ private: } T from_string (std::string const & s) const { - // XXX LocaleGuard std::stringstream t (s); T v; - t.precision (12); // in case its floating point t >> v; return v; } }; +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 */ #endif /* __pbd_properties_h__ */ diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h index 02224bb5e1..9ef1a9ef73 100644 --- a/libs/pbd/pbd/stateful.h +++ b/libs/pbd/pbd/stateful.h @@ -21,10 +21,12 @@ #define __pbd_stateful_h__ #include <string> +#include <list> #include <cassert> #include "pbd/id.h" #include "pbd/xml++.h" #include "pbd/enumwriter.h" +#include "pbd/properties.h" class XMLNode; @@ -34,201 +36,6 @@ namespace sys { class path; } -enum Change { - range_guarantee = ~0 -}; - -Change new_change (); - -/** Base (non template) part of State */ -class StateBase -{ -public: - StateBase (std::string const & p, Change c) - : _have_old (false) - , _xml_property_name (p) - , _change (c) - { - - } - - /** Forget about any old value for this state */ - void clear_history () { - _have_old = false; - } - - virtual void diff (XMLNode *, XMLNode *) const = 0; - virtual Change set_state (XMLNode const &) = 0; - virtual void add_state (XMLNode &) const = 0; - -protected: - bool _have_old; - std::string _xml_property_name; - Change _change; -}; - -/** Parent class for classes which represent a single piece of state in a Stateful object */ -template <class T> -class StateTemplate : public StateBase -{ -public: - StateTemplate (std::string const & p, Change c, T const & v) - : StateBase (p, c) - , _current (v) - { - - } - - StateTemplate<T> & operator= (StateTemplate<T> const & s) { - /* XXX: isn't there a nicer place to do this? */ - _have_old = s._have_old; - _xml_property_name = s._xml_property_name; - _change = s._change; - - _current = s._current; - _old = s._old; - return *this; - } - - T & operator= (T const & v) { - set (v); - return _current; - } - - T & operator+= (T const & v) { - set (_current + v); - return _current; - } - - bool operator== (const T& other) const { - return _current == other; - } - - bool operator!= (const T& other) const { - return _current != other; - } - - operator T const & () const { - return _current; - } - - T const & val () const { - return _current; - } - - void diff (XMLNode* old, XMLNode* current) const { - if (_have_old) { - old->add_property (_xml_property_name.c_str(), to_string (_old)); - current->add_property (_xml_property_name.c_str(), to_string (_current)); - } - } - - /** Try to set state from the property of an XML node. - * @param node XML node. - * @return Change effected, or 0. - */ - Change set_state (XMLNode const & node) { - XMLProperty const * p = node.property (_xml_property_name.c_str()); - - if (p) { - T const v = from_string (p->value ()); - - if (v == _current) { - return Change (0); - } - - set (v); - return _change; - } - - return Change (0); - } - - void add_state (XMLNode & node) const { - node.add_property (_xml_property_name.c_str(), to_string (_current)); - } - -protected: - void set (T const & v) { - _old = _current; - _have_old = true; - _current = v; - } - - virtual std::string to_string (T const & v) const = 0; - virtual T from_string (std::string const & s) const = 0; - - T _current; - T _old; -}; - -template<class T> -std::ostream& operator<< (std::ostream& os, StateTemplate<T> const & s) -{ - os << s.val(); - return os; -} - -/** Representation of a single piece of state in a Stateful; for use - * with types that can be written to / read from stringstreams. - */ -template <class T> -class State : public StateTemplate<T> -{ -public: - State (std::string const & p, Change c, T const & v) - : StateTemplate<T> (p, c, v) - { - - } - - T & operator= (T const & v) { - this->set (v); - return this->_current; - } - -private: - std::string to_string (T const & v) const { - std::stringstream s; - s.precision (12); // in case its floating point - s << v; - return s.str (); - } - - T from_string (std::string const & s) const { - std::stringstream t (s); - T v; - t.precision (12); // in case its floating point - t >> v; - return v; - } -}; - -template <class T> -class EnumState : public StateTemplate<T> -{ -public: - EnumState (std::string const & p, Change c, T const & v) - : StateTemplate<T> (p, c, v) - { - - } - - T & operator= (T const & v) { - this->set (v); - return this->_current; - } - -private: - std::string to_string (T const & v) const { - return enum_2_string (v); - } - - T from_string (std::string const & v) const { - return T (string_2_enum (v, this->_current)); - } -}; - /** Base class for objects with saveable and undoable state */ class Stateful { public: @@ -236,14 +43,21 @@ class Stateful { virtual ~Stateful(); virtual XMLNode& get_state (void) = 0; - virtual int set_state (const XMLNode&, int version) = 0; + /* derived types do not have to implement this, but probably should + give it serious attention. + */ + virtual PropertyChange set_property (const PropertyBase&) { return PropertyChange (0); } - void add_state (StateBase & s) { - _states.push_back (&s); + PropertyChange set_properties (const PropertyList&); + + void add_property (PropertyBase& s) { + _properties.add (s); } - /* Extra XML nodes */ + /* Extra XML node: so that 3rd parties can attach state to the XMLNode + representing the state of this object. + */ void add_extra_xml (XMLNode&); XMLNode *extra_xml (const std::string& str); @@ -251,7 +65,8 @@ class Stateful { const PBD::ID& id() const { return _id; } void clear_history (); - std::pair<XMLNode *, XMLNode*> diff (); + std::pair<XMLNode *, XMLNode*> diff () const; + void changed (PropertyChange&) const; static int current_state_version; static int loading_state_version; @@ -260,15 +75,25 @@ class Stateful { void add_instant_xml (XMLNode&, const sys::path& directory_path); XMLNode *instant_xml (const std::string& str, const sys::path& directory_path); - Change set_state_using_states (XMLNode const &); - void add_states (XMLNode &); + void add_properties (XMLNode &); + /* derived types can call this from ::set_state() (or elsewhere) + to get basic property setting done. + */ + PropertyChange set_properties (XMLNode const &); + + + /* derived classes can implement this to do cross-checking + of property values after either a PropertyList or XML + driven property change. + */ + virtual void post_set () { }; XMLNode *_extra_xml; XMLNode *_instant_xml; PBD::ID _id; std::string _xml_node_name; ///< name of node to use for this object in XML - std::list<StateBase*> _states; ///< state variables that this object has + OwnedPropertyList _properties; }; } // namespace PBD |