1 /* 2 * Copyright (C) 2010-2014 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2010 Carl Hetherington <carl@carlh.net> 4 * Copyright (C) 2013-2014 John Emmas <john@creativepost.co.uk> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21 #ifndef __libpbd_property_basics_h__ 22 #define __libpbd_property_basics_h__ 23 24 #include <glib.h> 25 #include <set> 26 #include <vector> 27 28 #include "pbd/libpbd_visibility.h" 29 #include "pbd/xml++.h" 30 31 class Command; 32 33 namespace PBD { 34 35 class LIBPBD_API PropertyList; 36 class LIBPBD_API StatefulDiffCommand; 37 38 /** A unique identifier for a property of a Stateful object */ 39 typedef GQuark PropertyID; 40 41 template<typename T> 42 struct LIBPBD_TEMPLATE_API PropertyDescriptor { PropertyDescriptorPropertyDescriptor43 PropertyDescriptor () : property_id (0) {} PropertyDescriptorPropertyDescriptor44 PropertyDescriptor (PropertyID pid) : property_id (pid) {} 45 46 PropertyID property_id; 47 typedef T value_type; 48 }; 49 50 /** A list of IDs of Properties that have changed in some situation or other */ 51 class LIBPBD_TEMPLATE_API PropertyChange : public std::set<PropertyID> 52 { 53 public: PropertyChange()54 LIBPBD_TEMPLATE_MEMBER_API PropertyChange() {} ~PropertyChange()55 LIBPBD_TEMPLATE_MEMBER_API ~PropertyChange() {} 56 57 template<typename T> PropertyChange(PropertyDescriptor<T> p); 58 PropertyChange(const PropertyChange & other)59 LIBPBD_TEMPLATE_MEMBER_API PropertyChange(const PropertyChange& other) : std::set<PropertyID> (other) {} 60 61 LIBPBD_TEMPLATE_MEMBER_API PropertyChange operator=(const PropertyChange& other) { 62 clear (); 63 insert (other.begin (), other.end ()); 64 return *this; 65 } 66 67 template<typename T> PropertyChange operator=(PropertyDescriptor<T> p); 68 template<typename T> bool contains (PropertyDescriptor<T> p) const; 69 contains(const PropertyChange & other)70 LIBPBD_TEMPLATE_MEMBER_API bool contains (const PropertyChange& other) const { 71 for (const_iterator x = other.begin (); x != other.end (); ++x) { 72 if (find (*x) != end ()) { 73 return true; 74 } 75 } 76 return false; 77 } 78 add(PropertyID id)79 void add (PropertyID id) { insert (id); } add(const PropertyChange & other)80 void add (const PropertyChange& other) { insert (other.begin (), other.end ()); } 81 template<typename T> void add (PropertyDescriptor<T> p); 82 }; 83 84 /** Base (non template) part of Property 85 * Properties are used for two main reasons: 86 * - to handle current state (when serializing Stateful objects) 87 * - to handle history since some operation was started (when making StatefulDiffCommands for undo) 88 */ 89 class LIBPBD_API PropertyBase 90 { 91 public: PropertyBase(PropertyID pid)92 PropertyBase (PropertyID pid) 93 : _property_id (pid) 94 {} 95 ~PropertyBase()96 virtual ~PropertyBase () {} 97 98 99 /* MANAGEMENT OF Stateful STATE */ 100 101 /** Set the value of this property from a Stateful node. 102 * @return true if the value was set. 103 */ 104 virtual bool set_value (XMLNode const &) = 0; 105 106 /** Get this property's value and put it into a Stateful node */ 107 virtual void get_value (XMLNode& node) const = 0; 108 109 110 /* MANAGEMENT OF HISTORY */ 111 112 /** Forget about any old changes to this property's value */ 113 virtual void clear_changes () = 0; 114 115 /** Tell any things we own to forget about their old values */ clear_owned_changes()116 virtual void clear_owned_changes () {} 117 118 /** @return true if this property has changed in value since construction or since 119 * the last call to clear_changes (), whichever was more recent. 120 */ 121 virtual bool changed () const = 0; 122 123 /** Invert the changes in this property */ 124 virtual void invert () = 0; 125 126 127 /* TRANSFERRING HISTORY TO / FROM A StatefulDiffCommand */ 128 129 /** Get any changes in this property as XML and add them to a 130 * StatefulDiffCommand node. 131 */ 132 virtual void get_changes_as_xml (XMLNode *) const = 0; 133 134 /** If this Property has changed, clone it and add it to a given list. 135 * Used for making StatefulDiffCommands. 136 */ 137 virtual void get_changes_as_properties (PropertyList& changes, Command *) const = 0; 138 139 /** Collect StatefulDiffCommands for changes to anything that we own */ rdiff(std::vector<Command * > &)140 virtual void rdiff (std::vector<Command*> &) const {} 141 142 /** Look in an XML node written by get_changes_as_xml and, if XML from this property 143 * is found, create a property with the changes from the XML. 144 */ clone_from_xml(const XMLNode &)145 virtual PropertyBase* clone_from_xml (const XMLNode &) const { return 0; } 146 147 148 /* VARIOUS */ 149 150 virtual PropertyBase* clone () const = 0; 151 152 /** Set this property's current state from another */ 153 virtual void apply_changes (PropertyBase const *) = 0; 154 property_name()155 const gchar* property_name () const { return g_quark_to_string (_property_id); } property_id()156 PropertyID property_id () const { return _property_id; } 157 158 bool operator==(PropertyID pid) const { 159 return _property_id == pid; 160 } 161 162 protected: 163 /* copy construction only by subclasses */ PropertyBase(PropertyBase const & b)164 PropertyBase (PropertyBase const & b) 165 : _property_id (b._property_id) 166 {} 167 168 private: 169 PropertyID _property_id; 170 171 }; 172 173 } 174 175 #endif /* __libpbd_property_basics_h__ */ 176