summaryrefslogtreecommitdiff
path: root/libs/pbd/pbd/stateful.h
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-02-09 14:44:01 +0000
committerCarl Hetherington <carl@carlh.net>2010-02-09 14:44:01 +0000
commita5c59175eb561cca6b704d6c50ee20290cc9a210 (patch)
treed75c4749252b92ede3131e47091c1298f782dc98 /libs/pbd/pbd/stateful.h
parent76ad2dfea0c53757530483ef3000caf9583441ec (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.h116
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