#include <sstream>
#include <list>
#include <set>
-#include <glib.h>
+#include <iostream>
#include "pbd/xml++.h"
#include "pbd/property_basics.h"
#include "pbd/property_list.h"
+#include "pbd/enumwriter.h"
namespace PBD {
public:
PropertyTemplate (PropertyDescriptor<T> p, T const& v)
: PropertyBase (p.property_id)
+ , _have_old (false)
, _current (v)
{}
+ PropertyTemplate (PropertyDescriptor<T> p, T const& o, T const& c)
+ : PropertyBase (p.property_id)
+ , _have_old (true)
+ , _current (c)
+ , _old (o)
+ {}
+
PropertyTemplate<T>& operator=(PropertyTemplate<T> const& s) {
/* XXX: isn't there a nicer place to do this? */
_have_old = s._have_old;
return _current;
}
- /** If this property has been changed since the last clear_history() call
- (or its construction), add an (XML) property describing the old value
- to the XMLNode @param old and another describing the current value to
- the XMLNode @param current.
- */
- void add_history_state (XMLNode* history_node) const {
- history_node->add_property (property_name(), to_string (_current));
+ void clear_changes () {
+ _have_old = false;
}
- /** Try to set state from the property of an XML node.
- * @param node XML node.
- * @return true if the value of the property is changed
- */
- bool set_state_from_owner_state (XMLNode const& owner_state) {
+ void get_changes_as_xml (XMLNode* history_node) const {
+ XMLNode* node = history_node->add_child (property_name());
+ node->add_property ("from", to_string (_old));
+ node->add_property ("to", to_string (_current));
+ }
- XMLProperty const* p = owner_state.property (property_name());
+ bool set_value (XMLNode const & node) {
+
+ XMLProperty const* p = node.property (property_name());
if (p) {
T const v = from_string (p->value ());
return false;
}
- void add_state_to_owner_state (XMLNode& owner_state) const {
- owner_state.add_property (property_name(), to_string (_current));
+ void get_value (XMLNode & node) const {
+ node.add_property (property_name(), to_string (_current));
+ }
+
+ bool changed () const { return _have_old; }
+
+ void apply_changes (PropertyBase const * p) {
+ T v = dynamic_cast<const PropertyTemplate<T>* > (p)->val ();
+ std::cout << "Apply changes: " << v << " cf " << _current << "\n";
+ if (v != _current) {
+ set (v);
+ }
+ }
+
+ void invert () {
+ T const tmp = _current;
+ _current = _old;
+ _old = tmp;
+ std::cout << "Inverted to " << _old << " -> " << _current << "\n";
}
protected:
{}
void set (T const& v) {
- _old = _current;
- _have_old = true;
- _current = v;
+ if (v != _current) {
+ if (!_have_old) {
+ _old = _current;
+ _have_old = true;
+ } else {
+ if (v == _old) {
+ /* value has been reset to the value
+ at the start of a history transaction,
+ before clear_changes() is called.
+ thus there is effectively no apparent
+ history for this property.
+ */
+ _have_old = false;
+ }
+ }
+
+ _current = v;
+ }
}
virtual std::string to_string (T const& v) const = 0;
virtual T from_string (std::string const& s) const = 0;
+ bool _have_old;
T _current;
T _old;
};
Property (PropertyDescriptor<T> q, T const& v)
: PropertyTemplate<T> (q, v)
{}
-
- void diff (PropertyList& before, PropertyList& after) const {
+
+ Property (PropertyDescriptor<T> q, T const& o, T const& c)
+ : PropertyTemplate<T> (q, o, c)
+ {}
+
+ Property<T>* clone () const {
+ return new Property<T> (*this);
+ }
+
+ void get_changes_as_properties (PropertyList& changes, Command *) const {
if (this->_have_old) {
- before.add (new Property<T> (this->property_id(), this->_old));
- after.add (new Property<T> (this->property_id(), this->_current));
+ changes.add (new Property<T> (*this));
}
}
- Property<T>* maybe_clone_self_if_found_in_history_node (const XMLNode& node) const {
- const XMLProperty* prop = node.property (this->property_name());
- if (!prop) {
- return 0;
- }
- return new Property<T> (this->property_id(), from_string (prop->value()));
+ Property<T>* clone_from_xml (const XMLNode& node) const {
+ XMLNodeList const & children = node.children ();
+ XMLNodeList::const_iterator i = children.begin();
+ while (i != children.end() && (*i)->name() != this->property_name()) {
+ ++i;
+ }
+
+ if (i == children.end()) {
+ return 0;
+ }
+ XMLProperty* from = (*i)->property ("from");
+ XMLProperty* to = (*i)->property ("to");
+
+ if (!from || !to) {
+ return 0;
+ }
+
+ return new Property<T> (this->property_id(), from_string (from->value()), from_string (to->value ()));
}
T & operator=(T const& v) {
* std::locale aborting on OS X if used with anything
* other than C or POSIX locales.
*/
- std::string to_string (T const& v) const {
+ virtual std::string to_string (T const& v) const {
std::stringstream s;
s.precision (12); // in case its floating point
s << v;
return s.str ();
}
- T from_string (std::string const& s) const {
+ virtual T from_string (std::string const& s) const {
std::stringstream t (s);
T v;
t >> v;
: PropertyTemplate<std::string> (q, v)
{}
- void diff (PropertyList& before, PropertyList& after) const {
+ Property<std::string>* clone () const {
+ return new Property<std::string> (*this);
+ }
+
+ void get_changes_as_properties (PropertyList& changes, Command* /*ignored*/) const {
if (this->_have_old) {
- before.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_old));
- after.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_current));
- }
+ changes.add (new Property<std::string> (*this));
+ }
}
std::string & operator=(std::string const& v) {
};
+template<class T>
+class EnumProperty : public Property<T>
+{
+public:
+ EnumProperty (PropertyDescriptor<T> q, T const& v)
+ : Property<T> (q, v)
+ {}
+
+ T & operator=(T const& v) {
+ this->set (v);
+ return this->_current;
+ }
+
+private:
+ std::string to_string (T const & v) const {
+ return enum_2_string (v);
+ }
+
+ T from_string (std::string const & s) const {
+ return static_cast<T> (string_2_enum (s, this->_current));
+ }
+};
+
} /* namespace PBD */
#include "pbd/property_list_impl.h"