2 Copyright (C) 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_properties_h__
21 #define __pbd_properties_h__
29 #include "pbd/xml++.h"
30 #include "pbd/property_basics.h"
31 #include "pbd/property_list.h"
35 /** Parent class for classes which represent a single scalar property in a Stateful object
38 class PropertyTemplate : public PropertyBase
41 PropertyTemplate (PropertyDescriptor<T> p, T const& v)
42 : PropertyBase (p.property_id)
47 PropertyTemplate<T>& operator=(PropertyTemplate<T> const& s) {
48 /* XXX: isn't there a nicer place to do this? */
49 _have_old = s._have_old;
50 _property_id = s._property_id;
52 _current = s._current;
57 T & operator=(T const& v) {
62 T & operator+=(T const& v) {
67 bool operator==(const T& other) const {
68 return _current == other;
71 bool operator!=(const T& other) const {
72 return _current != other;
75 operator T const &() const {
79 T const& val () const {
83 void clear_history () {
87 void add_history_state (XMLNode* history_node) const {
88 /* We can get to the current state of a scalar property like this one simply
89 by knowing what the new state is.
91 history_node->add_property (property_name(), to_string (_current));
94 /** Try to set state from the property of an XML node.
95 * @param node XML node.
96 * @return true if the value of the property is changed
98 bool set_state_from_owner_state (XMLNode const& owner_state) {
100 XMLProperty const* p = owner_state.property (property_name());
103 T const v = from_string (p->value ());
114 void add_state_to_owner_state (XMLNode& owner_state) const {
115 owner_state.add_property (property_name(), to_string (_current));
118 bool changed () const { return _have_old; }
119 void set_state_from_property (PropertyBase const * p) {
120 T v = dynamic_cast<const PropertyTemplate<T>* > (p)->val ();
127 /** Constructs a PropertyTemplate with a default
128 value for _old and _current.
131 PropertyTemplate (PropertyDescriptor<T> p)
132 : PropertyBase (p.property_id)
135 void set (T const& v) {
143 virtual std::string to_string (T const& v) const = 0;
144 virtual T from_string (std::string const& s) const = 0;
152 std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s)
154 return os << s.val ();
157 /** Representation of a single piece of scalar state in a Stateful; for use
158 * with types that can be written to / read from stringstreams.
161 class Property : public PropertyTemplate<T>
164 Property (PropertyDescriptor<T> q, T const& v)
165 : PropertyTemplate<T> (q, v)
168 void diff (PropertyList& undo, PropertyList& redo) const {
169 if (this->_have_old) {
170 undo.add (new Property<T> (this->property_id(), this->_old));
171 redo.add (new Property<T> (this->property_id(), this->_current));
175 Property<T>* maybe_clone_self_if_found_in_history_node (const XMLNode& node) const {
176 const XMLProperty* prop = node.property (this->property_name());
180 return new Property<T> (this->property_id(), from_string (prop->value()));
183 T & operator=(T const& v) {
185 return this->_current;
189 friend class PropertyFactory;
191 Property (PropertyDescriptor<T> q)
192 : PropertyTemplate<T> (q)
195 /* Note that we do not set a locale for the streams used
196 * in to_string() or from_string(), because we want the
197 * format to be portable across locales (i.e. C or
198 * POSIX). Also, there is the small matter of
199 * std::locale aborting on OS X if used with anything
200 * other than C or POSIX locales.
202 std::string to_string (T const& v) const {
204 s.precision (12); // in case its floating point
209 T from_string (std::string const& s) const {
210 std::stringstream t (s);
218 /** Specialization, for std::string which is common and special (see to_string() and from_string()
219 * Using stringstream to read from a std::string is easy to get wrong because of whitespace
223 class Property<std::string> : public PropertyTemplate<std::string>
226 Property (PropertyDescriptor<std::string> q, std::string const& v)
227 : PropertyTemplate<std::string> (q, v)
230 void diff (PropertyList& before, PropertyList& after) const {
231 if (this->_have_old) {
232 before.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_old));
233 after.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_current));
237 std::string & operator=(std::string const& v) {
239 return this->_current;
243 std::string to_string (std::string const& v) const {
247 std::string from_string (std::string const& s) const {
253 } /* namespace PBD */
255 #include "pbd/property_list_impl.h"
256 #include "pbd/property_basics_impl.h"
258 #endif /* __pbd_properties_h__ */