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== (const T& other) const {
104 return _current == other;
107 bool operator!= (const T& other) const {
108 return _current != other;
111 operator T const & () const {
115 T const & val () 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 {
193 s.precision (12); // in case its floating point
198 T from_string (std::string const & s) const {
199 std::stringstream t (s);
201 t.precision (12); // in case its floating point
208 class EnumState : public StateTemplate<T>
211 EnumState (std::string const & p, Change c, T const & v)
212 : StateTemplate<T> (p, c, v)
217 T & operator= (T const & v) {
219 return this->_current;
223 std::string to_string (T const & v) const {
224 return enum_2_string (v);
227 T from_string (std::string const & v) const {
228 return T (string_2_enum (v, this->_current));
232 /** Base class for objects with saveable and undoable state */
238 virtual XMLNode& get_state (void) = 0;
240 virtual int set_state (const XMLNode&, int version) = 0;
242 void add_state (StateBase & s) {
243 _states.push_back (&s);
246 /* Extra XML nodes */
248 void add_extra_xml (XMLNode&);
249 XMLNode *extra_xml (const std::string& str);
251 const PBD::ID& id() const { return _id; }
253 void clear_history ();
254 std::pair<XMLNode *, XMLNode*> diff ();
256 static int current_state_version;
257 static int loading_state_version;
261 void add_instant_xml (XMLNode&, const sys::path& directory_path);
262 XMLNode *instant_xml (const std::string& str, const sys::path& directory_path);
263 Change set_state_using_states (XMLNode const &);
264 void add_states (XMLNode &);
267 XMLNode *_instant_xml;
270 std::string _xml_node_name; ///< name of node to use for this object in XML
271 std::list<StateBase*> _states; ///< state variables that this object has
276 #endif /* __pbd_stateful_h__ */