2 Copyright (C) 2000-2010 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __pbd_stateful_h__
21 #define __pbd_stateful_h__
26 #include "pbd/xml++.h"
27 #include "pbd/enumwriter.h"
43 /** Base (non template) part of State */
47 StateBase (std::string const & p, Change c)
49 , _xml_property_name (p)
55 /** Forget about any old value for this state */
56 void clear_history () {
60 virtual void diff (XMLNode *, XMLNode *) const = 0;
61 virtual Change set_state (XMLNode const &) = 0;
62 virtual void add_state (XMLNode &) const = 0;
66 std::string _xml_property_name;
70 /** Parent class for classes which represent a single piece of state in a Stateful object */
72 class StateTemplate : public StateBase
75 StateTemplate (std::string const & p, Change c, T const & v)
82 StateTemplate<T> & operator= (StateTemplate<T> const & s) {
83 /* XXX: isn't there a nicer place to do this? */
84 _have_old = s._have_old;
85 _xml_property_name = s._xml_property_name;
88 _current = s._current;
93 T & operator= (T const & v) {
98 T & operator+= (T const & v) {
103 bool operator== (std::string const & o) const {
104 return o == to_string (_current);
107 bool operator!= (std::string const & o) const {
108 return o != to_string (_current);
111 operator T const & () const {
115 T const & get () const {
119 void diff (XMLNode* old, XMLNode* current) const {
121 old->add_property (_xml_property_name.c_str(), to_string (_old));
122 current->add_property (_xml_property_name.c_str(), to_string (_current));
126 /** Try to set state from the property of an XML node.
127 * @param node XML node.
128 * @return Change effected, or 0.
130 Change set_state (XMLNode const & node) {
131 XMLProperty const * p = node.property (_xml_property_name.c_str());
134 T const v = from_string (p->value ());
147 void add_state (XMLNode & node) const {
148 node.add_property (_xml_property_name.c_str(), to_string (_current));
152 void set (T const & v) {
158 virtual std::string to_string (T const & v) const = 0;
159 virtual T from_string (std::string const & s) const = 0;
166 std::ostream& operator<< (std::ostream& os, StateTemplate<T> const & s)
172 /** Representation of a single piece of state in a Stateful; for use
173 * with types that can be written to / read from stringstreams.
176 class State : public StateTemplate<T>
179 State (std::string const & p, Change c, T const & v)
180 : StateTemplate<T> (p, c, v)
185 T & operator= (T const & v) {
187 return this->_current;
191 std::string to_string (T const & v) const {
197 T from_string (std::string const & s) const {
198 std::stringstream t (s);
206 class EnumState : public StateTemplate<T>
209 EnumState (std::string const & p, Change c, T const & v)
210 : StateTemplate<T> (p, c, v)
215 T & operator= (T const & v) {
217 return this->_current;
221 std::string to_string (T const & v) const {
222 return enum_2_string (v);
225 T from_string (std::string const & v) const {
226 return T (string_2_enum (v, this->_current));
230 /** Base class for objects with saveable and undoable state */
236 virtual XMLNode& get_state (void) = 0;
238 virtual int set_state (const XMLNode&, int version) = 0;
240 void add_state (StateBase & s) {
241 _states.push_back (&s);
244 /* Extra XML nodes */
246 void add_extra_xml (XMLNode&);
247 XMLNode *extra_xml (const std::string& str);
249 const PBD::ID& id() const { return _id; }
251 void clear_history ();
252 std::pair<XMLNode *, XMLNode*> diff ();
254 static int current_state_version;
255 static int loading_state_version;
259 void add_instant_xml (XMLNode&, const sys::path& directory_path);
260 XMLNode *instant_xml (const std::string& str, const sys::path& directory_path);
261 Change set_state_using_states (XMLNode const &);
262 void add_states (XMLNode &);
265 XMLNode *_instant_xml;
268 std::string _xml_node_name; ///< name of node to use for this object in XML
269 std::list<StateBase*> _states; ///< state variables that this object has
274 #endif /* __pbd_stateful_h__ */