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"
32 #include "pbd/enumwriter.h"
36 /** 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 (PropertyDescriptor<T> p, T const& o, T const& c)
48 : PropertyBase (p.property_id)
54 PropertyTemplate (PropertyDescriptor<T> p, PropertyTemplate<T> const & s)
55 : PropertyBase (p.property_id)
57 , _current (s._current)
61 /* OPERATORS / ACCESSORS */
63 T & operator=(T const& v) {
68 /* This will mean that, if fred and jim are both PropertyTemplates,
69 * fred = jim will result in fred taking on jim's current value,
70 * but NOT jim's property ID.
72 PropertyTemplate<T> & operator= (PropertyTemplate<T> const & p) {
77 T & operator+=(T const& v) {
82 bool operator==(const T& other) const {
83 return _current == other;
86 bool operator!=(const T& other) const {
87 return _current != other;
90 operator T const &() const {
94 T const& val () const {
99 /* MANAGEMENT OF Stateful State */
101 bool set_value (XMLNode const & node) {
103 XMLProperty const* p = node.property (property_name());
106 T const v = from_string (p->value ());
117 void get_value (XMLNode & node) const {
118 node.add_property (property_name(), to_string (_current));
122 /* MANAGEMENT OF HISTORY */
124 void clear_changes () {
128 bool changed () const { return _have_old; }
131 T const tmp = _current;
137 /* TRANSFERRING HISTORY TO / FROM A StatefulDiffCommand */
139 void get_changes_as_xml (XMLNode* history_node) const {
140 XMLNode* node = history_node->add_child (property_name());
141 node->add_property ("from", to_string (_old));
142 node->add_property ("to", to_string (_current));
145 void get_changes_as_properties (PropertyList& changes, Command *) const {
146 if (this->_have_old) {
147 changes.add (clone ());
154 void apply_changes (PropertyBase const * p) {
155 T v = dynamic_cast<const PropertyTemplate<T>* > (p)->val ();
163 void set (T const& v) {
170 /* value has been reset to the value
171 at the start of a history transaction,
172 before clear_changes() is called.
173 thus there is effectively no apparent
174 history for this property.
184 virtual std::string to_string (T const& v) const = 0;
185 virtual T from_string (std::string const& s) const = 0;
192 /* disallow copy-construction; it's not obvious whether it should mean
193 a copy of just the value, or the value and property ID.
195 PropertyTemplate (PropertyTemplate<T> const &);
199 std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s)
201 return os << s.val ();
204 /** Representation of a single piece of scalar state in a Stateful; for use
205 * with types that can be written to / read from stringstreams.
208 class Property : public PropertyTemplate<T>
211 Property (PropertyDescriptor<T> q, T const& v)
212 : PropertyTemplate<T> (q, v)
215 Property (PropertyDescriptor<T> q, T const& o, T const& c)
216 : PropertyTemplate<T> (q, o, c)
219 Property (PropertyDescriptor<T> q, Property<T> const& v)
220 : PropertyTemplate<T> (q, v)
223 Property<T>* clone () const {
224 return new Property<T> (this->property_id(), this->_old, this->_current);
227 Property<T>* clone_from_xml (const XMLNode& node) const {
228 XMLNodeList const & children = node.children ();
229 XMLNodeList::const_iterator i = children.begin();
230 while (i != children.end() && (*i)->name() != this->property_name()) {
234 if (i == children.end()) {
237 XMLProperty* from = (*i)->property ("from");
238 XMLProperty* to = (*i)->property ("to");
244 return new Property<T> (this->property_id(), from_string (from->value()), from_string (to->value ()));
247 T & operator=(T const& v) {
249 return this->_current;
253 friend class PropertyFactory;
255 /* no copy-construction */
256 Property (Property<T> const &);
258 /* Note that we do not set a locale for the streams used
259 * in to_string() or from_string(), because we want the
260 * format to be portable across locales (i.e. C or
261 * POSIX). Also, there is the small matter of
262 * std::locale aborting on OS X if used with anything
263 * other than C or POSIX locales.
265 virtual std::string to_string (T const& v) const {
267 s.precision (12); // in case its floating point
272 virtual T from_string (std::string const& s) const {
273 std::stringstream t (s);
281 /** Specialization, for std::string which is common and special (see to_string() and from_string()
282 * Using stringstream to read from a std::string is easy to get wrong because of whitespace
286 class Property<std::string> : public PropertyTemplate<std::string>
289 Property (PropertyDescriptor<std::string> d, std::string const & v)
290 : PropertyTemplate<std::string> (d, v)
293 Property (PropertyDescriptor<std::string> d, std::string const & o, std::string const & c)
294 : PropertyTemplate<std::string> (d, o, c)
297 Property<std::string>* clone () const {
298 return new Property<std::string> (this->property_id(), _old, _current);
301 std::string & operator= (std::string const& v) {
303 return this->_current;
307 std::string to_string (std::string const& v) const {
311 std::string from_string (std::string const& s) const {
315 /* no copy-construction */
316 Property (Property<std::string> const &);
320 class EnumProperty : public Property<T>
323 EnumProperty (PropertyDescriptor<T> q, T const& v)
327 T & operator=(T const& v) {
329 return this->_current;
333 std::string to_string (T const & v) const {
334 return enum_2_string (v);
337 T from_string (std::string const & s) const {
338 return static_cast<T> (string_2_enum (s, this->_current));
341 /* no copy-construction */
342 EnumProperty (EnumProperty const &);
345 } /* namespace PBD */
347 #include "pbd/property_list_impl.h"
348 #include "pbd/property_basics_impl.h"
350 #endif /* __pbd_properties_h__ */