X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Fpbd%2Fstateful.h;h=4808bc2911f816b3e6e5634342dab488a5bd0433;hb=0aac62e013e15e380001dafae39d554f8765a4a1;hp=60c1c6b23cfbd37f613469793210d544f6d91388;hpb=a5c59175eb561cca6b704d6c50ee20290cc9a210;p=ardour.git diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h index 60c1c6b23c..4808bc2911 100644 --- a/libs/pbd/pbd/stateful.h +++ b/libs/pbd/pbd/stateful.h @@ -21,9 +21,13 @@ #define __pbd_stateful_h__ #include +#include #include + #include "pbd/id.h" #include "pbd/xml++.h" +#include "pbd/property_basics.h" +#include "pbd/signals.h" class XMLNode; @@ -33,104 +37,8 @@ namespace sys { class path; } -/** Base (non template) part of State */ -class StateBase -{ -public: - StateBase (std::string const & p) - : _have_old (false) - , _xml_property_name (p) - { - - } - - StateBase (StateBase const & s) - : _have_old (s._have_old) - , _xml_property_name (s._xml_property_name) - { - - } - - /** Forget about any old value for this state */ - void clear_history () { - _have_old = false; - } - - virtual void diff (XMLNode *, XMLNode *) const = 0; - -protected: - bool _have_old; - std::string _xml_property_name; -}; - -/** Class to represent a single piece of state in a Stateful object */ -template -class State : public StateBase -{ -public: - State (std::string const & p, T const & v) - : StateBase (p) - , _current (v) - { - - } - - State (State const & s) - : StateBase (s) - { - _current = s._current; - _old = s._old; - } - - State & operator= (State const & s) { - /* XXX: isn't there a nicer place to do this? */ - _have_old = s._have_old; - _xml_property_name = s._xml_property_name; - - _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; - } - - operator T () const { - return _current; - } - - T const & get () const { - return _current; - } - - void diff (XMLNode* old, XMLNode* current) const { - if (_have_old) { - std::stringstream o; - o << _old; - old->add_property (_xml_property_name.c_str(), o.str().c_str()); - std::stringstream c; - c << _current; - current->add_property (_xml_property_name.c_str(), c.str().c_str()); - } - } - -private: - void set (T const & v) { - _old = _current; - _have_old = true; - _current = v; - } - - T _current; - T _old; -}; +class PropertyList; +class OwnedPropertyList; /** Base class for objects with saveable and undoable state */ class Stateful { @@ -139,37 +47,83 @@ class Stateful { virtual ~Stateful(); virtual XMLNode& get_state (void) = 0; - virtual int set_state (const XMLNode&, int version) = 0; - void add_state (StateBase & s) { - _states.push_back (&s); - } + virtual bool apply_changes (PropertyBase const &); + PropertyChange apply_changes (PropertyList const &); + + const OwnedPropertyList& properties() const { return *_properties; } + + void add_property (PropertyBase& 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); + XMLNode *extra_xml (const std::string& str, bool add_if_missing = false); + void save_extra_xml (const XMLNode&); const PBD::ID& id() const { return _id; } + bool set_id (const XMLNode&); + void set_id (const std::string&); + void reset_id (); + + /* history management */ + + void clear_changes (); + virtual void clear_owned_changes (); + PropertyList* get_changes_as_properties (Command *) const; + virtual void rdiff (std::vector &) const; + bool changed() const; + + /* create a property list from an XMLNode + */ + virtual PropertyList* property_factory (const XMLNode&) const; - void clear_history (); - std::pair diff (); + /* How stateful's notify of changes to their properties + */ + PBD::Signal1 PropertyChanged; static int current_state_version; static int loading_state_version; + virtual void suspend_property_changes (); + virtual void resume_property_changes (); + + bool property_changes_suspended() const { return g_atomic_int_get (const_cast(&_stateful_frozen)) > 0; } + protected: - void add_instant_xml (XMLNode&, const sys::path& directory_path); - XMLNode *instant_xml (const std::string& str, const sys::path& directory_path); + void add_instant_xml (XMLNode&, const std::string& directory_path); + XMLNode *instant_xml (const std::string& str, const std::string& directory_path); + void add_properties (XMLNode &); + + PropertyChange set_values (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 (const PropertyChange&) { }; XMLNode *_extra_xml; XMLNode *_instant_xml; - PBD::ID _id; + PBD::PropertyChange _pending_changed; + Glib::Threads::Mutex _lock; std::string _xml_node_name; ///< name of node to use for this object in XML - std::list _states; ///< state variables that this object has + OwnedPropertyList* _properties; + + virtual void send_change (const PropertyChange&); + /** derived classes can implement this in order to process a property change + within thaw() just before send_change() is called. + */ + virtual void mid_thaw (const PropertyChange&) { } + + private: + PBD::ID _id; + gint _stateful_frozen; }; } // namespace PBD