diff options
author | Carl Hetherington <carl@carlh.net> | 2010-02-09 14:44:01 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-02-09 14:44:01 +0000 |
commit | a5c59175eb561cca6b704d6c50ee20290cc9a210 (patch) | |
tree | d75c4749252b92ede3131e47091c1298f782dc98 /libs/pbd/pbd/stateful.h | |
parent | 76ad2dfea0c53757530483ef3000caf9583441ec (diff) |
Modify Stateful to allow undo to be done using differences in state.
git-svn-id: svn://localhost/ardour2/branches/3.0@6664 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/pbd/stateful.h')
-rw-r--r-- | libs/pbd/pbd/stateful.h | 116 |
1 files changed, 114 insertions, 2 deletions
diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h index 0204c8084a..60c1c6b23c 100644 --- a/libs/pbd/pbd/stateful.h +++ b/libs/pbd/pbd/stateful.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-2010 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,9 @@ #define __pbd_stateful_h__ #include <string> +#include <cassert> #include "pbd/id.h" +#include "pbd/xml++.h" class XMLNode; @@ -31,15 +33,119 @@ 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 T> +class State : public StateBase +{ +public: + State (std::string const & p, T const & v) + : StateBase (p) + , _current (v) + { + + } + + State (State<T> const & s) + : StateBase (s) + { + _current = s._current; + _old = s._old; + } + + State<T> & operator= (State<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; + + _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; +}; + +/** Base class for objects with saveable and undoable state */ class Stateful { public: - Stateful(); + 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); + } + /* Extra XML nodes */ void add_extra_xml (XMLNode&); @@ -47,6 +153,9 @@ class Stateful { const PBD::ID& id() const { return _id; } + void clear_history (); + std::pair<XMLNode *, XMLNode*> diff (); + static int current_state_version; static int loading_state_version; @@ -58,6 +167,9 @@ class Stateful { 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 }; } // namespace PBD |