1 #ifndef _GLIBMM_PROPERTY_H
2 #define _GLIBMM_PROPERTY_H
3
4 /* Copyright 2002 The gtkmm Development Team
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <glibmmconfig.h>
21 #include <glibmm/propertyproxy.h>
22 #include <glibmm/value.h>
23
24 namespace Glib
25 {
26
27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
28
29 #ifdef GLIBMM_CXX_CAN_USE_NAMESPACES_INSIDE_EXTERNC
30 // For the AIX xlC compiler, I can not find a way to do this without putting the functions in the
31 // global namespace. murrayc
32 extern "C" {
33 #endif // GLIBMM_CXX_CAN_USE_NAMESPACES_INSIDE_EXTERNC
34
35 GLIBMM_API
36 void custom_get_property_callback(
37 GObject* object, unsigned int property_id, GValue* value, GParamSpec* param_spec);
38
39 GLIBMM_API
40 void custom_set_property_callback(
41 GObject* object, unsigned int property_id, const GValue* value, GParamSpec* param_spec);
42
43 #ifdef GLIBMM_CXX_CAN_USE_NAMESPACES_INSIDE_EXTERNC
44 } // extern "C"
45 #endif // GLIBMM_CXX_CAN_USE_NAMESPACES_INSIDE_EXTERNC
46
47 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
48
49 /** This is the base class for Glib::Object properties.
50 *
51 * This class manages the generic parts of the object properties.
52 * Derived (templated) classes handle the specific value types.
53 */
54 class GLIBMM_API PropertyBase
55 {
56 public:
57 // noncopyable
58 PropertyBase(const PropertyBase&) = delete;
59 PropertyBase& operator=(const PropertyBase&) = delete;
60
61 /** Returns the name of the property.
62 */
63 Glib::ustring get_name() const;
64
65 /** Returns the nickname of the property.
66 */
67 Glib::ustring get_nick() const;
68
69 /** Returns the short description of the property.
70 */
71 Glib::ustring get_blurb() const;
72
73 /** Notifies the object containing the property that the property has changed.
74 * This emits the "notify" signal, passing the property name.
75 */
76 void notify();
77
78 protected:
79 Glib::Object* object_;
80 Glib::ValueBase value_;
81 GParamSpec* param_spec_;
82
83 /** This constructs a property of type @a value_type for the @a object.
84 * The property is not registered in the GObject object system
85 * until install_property() has been called. Derived classes do this in
86 * their constructors.
87 *
88 * The properties are usually installed during the initialization of the
89 * first instance of an object.
90 */
91 PropertyBase(Glib::Object& object, GType value_type);
92 ~PropertyBase() noexcept;
93
94 /**
95 * Checks if the property has already been installed.
96 */
97 bool lookup_property(const Glib::ustring& name);
98
99 /**
100 * Installs the property specified by the given @a param_spec.
101 */
102 void install_property(GParamSpec* param_spec);
103
104 /**
105 * Returns the name of the property.
106 */
107 const char* get_name_internal() const;
108
109 private:
110 #ifndef DOXYGEN_SHOULD_SKIP_THIS
111
112 friend void Glib::custom_get_property_callback(
113 GObject* object, unsigned int property_id, GValue* value, GParamSpec* param_spec);
114
115 friend void Glib::custom_set_property_callback(
116 GObject* object, unsigned int property_id, const GValue* value, GParamSpec* param_spec);
117
118 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
119 };
120
121 /** A Glib::Object property.
122 *
123 * This class wraps a GObject property, providing a C++ API to the GObject property
124 * system, for use with classes derived from Glib::Object or Glib::Interface.
125 *
126 * A property is a value associated with each instance of a type and some
127 * class data for each property:
128 * * Its unique name, used to identify the property.
129 * * A human-readable nick name.
130 * * A short description.
131 * * The default value and the minimum and maximum bounds (depending on the type of the property).
132 * * Flags, defining, among other things, whether the property can be read or written.
133 *
134 * This %Property class currently supports the name, nick name, description, default value and flags.
135 * The minimum and maximum bounds are set to the full range of the value.
136 * Because of internal implementation, flags shouldn't be set to values: Glib::PARAM_STATIC_NAME,
137 * Glib::PARAM_STATIC_NICK, Glib::PARAM_STATIC_BLURB, Glib::PARAM_CONSTRUCT and
138 * Glib::PARAM_CONSTRUCT_ONLY.
139 *
140 * The class information must be installed into the GObject system once per
141 * property, but this is handled automatically.
142 *
143 * Each property belongs to an object, inheriting from Glib::Object.
144 * A reference to the object must be passed to the constructor of the property.
145 *
146 * Each instance of a Glib::Object-derived type must construct the same properties
147 * (same type, same name) in the same order. One way to achieve this is to
148 * declare all properties as direct data members of the type.
149 *
150 * You may register new properties for your class (actually for the underlying GType)
151 * simply by adding a %Property instance as a class member.
152 * However, your constructor must call the Glib::ObjectBase constructor with a new GType name,
153 * in order to register a new GType.
154 *
155 * Example:
156 * @code
157 * class MyCellRenderer : public Gtk::CellRenderer
158 * {
159 * public:
160 * MyCellRenderer()
161 * :
162 * Glib::ObjectBase (typeid(MyCellRenderer)),
163 * Gtk::CellRenderer(),
164 * property_mybool (*this, "mybool", true),
165 * property_myint_ (*this, "myint", 42)
166 * {}
167 *
168 * virtual ~MyCellRenderer() {}
169 *
170 * // Glib::Property<> can be public,
171 * Glib::Property<bool> property_mybool;
172 * // or private, and combined with Glib::PropertyProxy<>.
173 * Glib::PropertyProxy<int> property_myint() { return property_myint_.get_proxy(); }
174 * Glib::PropertyProxy_ReadOnly<int> property_myint() const { return property_myint_.get_proxy(); }
175 *
176 * private:
177 * Glib::Property<int> property_myint_;
178 * };
179 * @endcode
180 *
181 * @par %Glib::Property and Gtk::Builder
182 * The new GType is registered, and the properties installed in the GType, when
183 * the first instance of the class is created. When the underlying GObject-derived
184 * instance is created before the wrapping Glib::Object-derived instance, you may
185 * have to first create a dummy instance just to register the GType.
186 * See the description of Gtk::Builder for instructions how to combine %Property
187 * with Gtk::Builder.
188 */
189 template <class T>
190 class Property : public PropertyBase
191 {
192 public:
193 using PropertyType = T;
194 using ValueType = Glib::Value<T>;
195
196 /** Constructs a property of the @a object with the specified @a name.
197 * For each instance of the object, the same property must be constructed with the same name.
198 */
199 Property(Glib::Object& object, const Glib::ustring& name);
200
201 /** Constructs a property of the @a object with the specified @a name and @a default_value.
202 * For each instance of the object, the same property must be constructed with the same name.
203 */
204 Property(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value);
205
206 /** Constructs a property of the @a object with the specified @a name, @a nick, @a blurb and
207 * @a flags.
208 * For each instance of the object, the same property must be constructed with the same name.
209 */
210 Property(Glib::Object& object, const Glib::ustring& name, const Glib::ustring& nick,
211 const Glib::ustring& blurb, Glib::ParamFlags flags);
212
213 /** Constructs a property of the @a object with the specified @a name, @a default_value, @a nick,
214 * @a blurb and @a flags.
215 * For each instance of the object, the same property must be constructed with the same name.
216 */
217 Property(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value,
218 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags);
219
220 /** Sets the value of the property to @a data.
221 * The object containing the property will be notified about the change.
222 */
223 inline void set_value(const PropertyType& data);
224
225 /** Returns the value of the property.
226 */
227 inline PropertyType get_value() const;
228
229 /** Sets the value of the property to @a data.
230 * The object containing the property will be notified about the change.
231 */
232 inline Property<T>& operator=(const PropertyType& data);
233
234 /** Returns the value of the property.
235 */
236 inline operator PropertyType() const;
237
238 /** Returns a proxy object that can be used to read or write this property.
239 */
240 inline Glib::PropertyProxy<T> get_proxy();
241
242 /** Returns a proxy object that can be used to read this property.
243 */
244 inline Glib::PropertyProxy_ReadOnly<T> get_proxy() const;
245 };
246
247 /** See Property.
248 * This property can be read, but not written, so there is no set_value() method.
249 */
250 template <class T>
251 class Property_ReadOnly : public PropertyBase
252 {
253 public:
254 typedef T PropertyType;
255 typedef Glib::Value<T> ValueType;
256
257 /** Constructs a property of the @a object with the specified @a name.
258 * For each instance of the object, the same property must be constructed with the same name.
259 */
260 Property_ReadOnly(Glib::Object& object, const Glib::ustring& name);
261
262 /** Constructs a property of the @a object with the specified @a name and @a default_value.
263 * For each instance of the object, the same property must be constructed with the same name.
264 */
265 Property_ReadOnly(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value);
266
267 /** Constructs a property of the @a object with the specified @a name, @a nick, @a blurb and
268 * @a flags.
269 * For each instance of the object, the same property must be constructed with the same name.
270 */
271 Property_ReadOnly(Glib::Object& object, const Glib::ustring& name, const Glib::ustring& nick,
272 const Glib::ustring& blurb, Glib::ParamFlags flags);
273
274 /** Constructs a property of the @a object with the specified @a name, @a default_value, @a nick,
275 * @a blurb and @a flags.
276 * For each instance of the object, the same property must be constructed with the same name.
277 */
278 Property_ReadOnly(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value,
279 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags);
280
281 /** Returns the value of the property.
282 */
283 inline PropertyType get_value() const;
284
285 /** Returns the value of the property.
286 */
287 inline operator PropertyType() const;
288
289 //TODO: Remove the non-const get_proxy() when we can break ABI.
290 /** Returns a proxy object that can be used to read this property.
291 */
292 inline Glib::PropertyProxy_ReadOnly<T> get_proxy();
293
294 /** Returns a proxy object that can be used to read this property.
295 */
296 inline Glib::PropertyProxy_ReadOnly<T> get_proxy() const;
297 };
298
299 /** See Property.
300 * This property can be written, but not read, so there is no get_value() method.
301 */
302 template <class T>
303 class Property_WriteOnly : public PropertyBase
304 {
305 public:
306 typedef T PropertyType;
307 typedef Glib::Value<T> ValueType;
308
309 /** Constructs a property of the @a object with the specified @a name.
310 * For each instance of the object, the same property must be constructed with the same name.
311 */
312 Property_WriteOnly(Glib::Object& object, const Glib::ustring& name);
313
314 /** Constructs a property of the @a object with the specified @a name and @a default_value.
315 * For each instance of the object, the same property must be constructed with the same name.
316 */
317 Property_WriteOnly(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value);
318
319 /** Constructs a property of the @a object with the specified @a name, @a nick, @a blurb and
320 * @a flags.
321 * For each instance of the object, the same property must be constructed with the same name.
322 */
323 Property_WriteOnly(Glib::Object& object, const Glib::ustring& name, const Glib::ustring& nick,
324 const Glib::ustring& blurb, Glib::ParamFlags flags);
325
326 /** Constructs a property of the @a object with the specified @a name, @a default_value, @a nick,
327 * @a blurb and @a flags.
328 * For each instance of the object, the same property must be constructed with the same name.
329 */
330 Property_WriteOnly(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value,
331 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags);
332
333 /** Sets the value of the property to @a data.
334 * The object containing the property will be notified about the change.
335 */
336 inline void set_value(const PropertyType& data);
337
338 /** Sets the value of the property to @a data.
339 * The object containing the property will be notified about the change.
340 */
341 inline Property_WriteOnly<T>& operator=(const PropertyType& data);
342
343 /** Returns a proxy object that can be used to write this property.
344 */
345 inline Glib::PropertyProxy_WriteOnly<T> get_proxy();
346 };
347
348 #ifndef DOXYGEN_SHOULD_SKIP_THIS
349
350 /**** Glib::Property<T> ****************************************************/
351
352 template <class T>
Property(Glib::Object & object,const Glib::ustring & name)353 Property<T>::Property(Glib::Object& object, const Glib::ustring& name)
354 : Property(object, name, Glib::ustring(), Glib::ustring(), Glib::PARAM_READWRITE)
355 {
356 }
357
358 template <class T>
Property(Glib::Object & object,const Glib::ustring & name,const typename Property<T>::PropertyType & default_value)359 Property<T>::Property(Glib::Object& object, const Glib::ustring& name,
360 const typename Property<T>::PropertyType& default_value)
361 : Property(object, name, default_value, Glib::ustring(),
362 Glib::ustring(), Glib::PARAM_READWRITE)
363 {
364 }
365
366 template <class T>
Property(Glib::Object & object,const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags)367 Property<T>::Property(Glib::Object& object, const Glib::ustring& name,
368 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags)
369 : PropertyBase(object, ValueType::value_type())
370 {
371 flags |= Glib::PARAM_READWRITE;
372
373 if (!lookup_property(name))
374 install_property(static_cast<ValueType&>(value_).create_param_spec(name, nick, blurb, flags));
375 }
376
377 template <class T>
Property(Glib::Object & object,const Glib::ustring & name,const PropertyType & default_value,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags)378 Property<T>::Property(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value,
379 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags)
380 :
381 PropertyBase(object, ValueType::value_type())
382 {
383 flags |= Glib::PARAM_READWRITE;
384
385 static_cast<ValueType&>(value_).set(default_value);
386
387 if (!lookup_property(name))
388 install_property(static_cast<ValueType&>(value_).create_param_spec(name, nick, blurb, flags));
389 }
390
391 template <class T>
392 inline void
set_value(const typename Property<T>::PropertyType & data)393 Property<T>::set_value(const typename Property<T>::PropertyType& data)
394 {
395 static_cast<ValueType&>(value_).set(data);
396 this->notify();
397 }
398
399 template <class T>
400 inline typename Property<T>::PropertyType
get_value()401 Property<T>::get_value() const
402 {
403 return static_cast<const ValueType&>(value_).get();
404 }
405
406 template <class T>
407 inline Property<T>&
408 Property<T>::operator=(const typename Property<T>::PropertyType& data)
409 {
410 static_cast<ValueType&>(value_).set(data);
411 this->notify();
412 return *this;
413 }
414
415 template <class T>
T()416 inline Property<T>::operator T() const
417 {
418 return static_cast<const ValueType&>(value_).get();
419 }
420
421 template <class T>
422 inline Glib::PropertyProxy<T>
get_proxy()423 Property<T>::get_proxy()
424 {
425 return Glib::PropertyProxy<T>(object_, get_name_internal());
426 }
427
428 template <class T>
429 inline Glib::PropertyProxy_ReadOnly<T>
get_proxy()430 Property<T>::get_proxy() const
431 {
432 return Glib::PropertyProxy_ReadOnly<T>(object_, get_name_internal());
433 }
434
435 /**** Glib::Property_ReadOnly<T> ****************************************************/
436
437 template <class T>
Property_ReadOnly(Glib::Object & object,const Glib::ustring & name)438 Property_ReadOnly<T>::Property_ReadOnly(Glib::Object& object, const Glib::ustring& name)
439 : Property_ReadOnly(object, name, Glib::ustring(), Glib::ustring(), Glib::PARAM_READABLE)
440 {
441 }
442
443 template <class T>
Property_ReadOnly(Glib::Object & object,const Glib::ustring & name,const typename Property_ReadOnly<T>::PropertyType & default_value)444 Property_ReadOnly<T>::Property_ReadOnly(Glib::Object& object, const Glib::ustring& name,
445 const typename Property_ReadOnly<T>::PropertyType& default_value)
446 : Property_ReadOnly(object, name, default_value, Glib::ustring(), Glib::ustring(),
447 Glib::PARAM_READABLE)
448 {
449 }
450
451 template <class T>
Property_ReadOnly(Glib::Object & object,const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags)452 Property_ReadOnly<T>::Property_ReadOnly(Glib::Object& object, const Glib::ustring& name,
453 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags)
454 : PropertyBase(object, ValueType::value_type())
455 {
456 flags |= Glib::PARAM_READABLE;
457 flags &= ~Glib::PARAM_WRITABLE;
458
459 if (!lookup_property(name))
460 install_property(static_cast<ValueType&>(value_).create_param_spec(name, nick, blurb, flags));
461 }
462
463 template <class T>
Property_ReadOnly(Glib::Object & object,const Glib::ustring & name,const PropertyType & default_value,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags)464 Property_ReadOnly<T>::Property_ReadOnly(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value,
465 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags)
466 : PropertyBase(object, ValueType::value_type())
467 {
468 flags |= Glib::PARAM_READABLE;
469 flags &= ~Glib::PARAM_WRITABLE;
470
471 static_cast<ValueType&>(value_).set(default_value);
472
473 if (!lookup_property(name))
474 install_property(static_cast<ValueType&>(value_).create_param_spec(name, nick, blurb, flags));
475 }
476
477 template <class T>
478 inline typename Property_ReadOnly<T>::PropertyType
get_value()479 Property_ReadOnly<T>::get_value() const
480 {
481 return static_cast<const ValueType&>(value_).get();
482 }
483
484 template <class T>
T()485 inline Property_ReadOnly<T>::operator T() const
486 {
487 return static_cast<const ValueType&>(value_).get();
488 }
489
490 template <class T>
491 inline Glib::PropertyProxy_ReadOnly<T>
get_proxy()492 Property_ReadOnly<T>::get_proxy()
493 {
494 return Glib::PropertyProxy_ReadOnly<T>(object_, get_name_internal());
495 }
496
497 template <class T>
498 inline Glib::PropertyProxy_ReadOnly<T>
get_proxy()499 Property_ReadOnly<T>::get_proxy() const
500 {
501 return Glib::PropertyProxy_ReadOnly<T>(object_, get_name_internal());
502 }
503
504 /**** Glib::Property_WriteOnly<T> ****************************************************/
505
506 template <class T>
Property_WriteOnly(Glib::Object & object,const Glib::ustring & name)507 Property_WriteOnly<T>::Property_WriteOnly(Glib::Object& object, const Glib::ustring& name)
508 : Property_WriteOnly(object, name, Glib::ustring(),
509 Glib::ustring(), Glib::PARAM_WRITABLE)
510 {
511 }
512
513 template <class T>
Property_WriteOnly(Glib::Object & object,const Glib::ustring & name,const typename Property_WriteOnly<T>::PropertyType & default_value)514 Property_WriteOnly<T>::Property_WriteOnly(Glib::Object& object, const Glib::ustring& name,
515 const typename Property_WriteOnly<T>::PropertyType& default_value)
516 : Property_WriteOnly(object, name, default_value, Glib::ustring(),
517 Glib::ustring(), Glib::PARAM_WRITABLE)
518 {
519 }
520
521 template <class T>
Property_WriteOnly(Glib::Object & object,const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags)522 Property_WriteOnly<T>::Property_WriteOnly(Glib::Object& object, const Glib::ustring& name,
523 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags)
524 : PropertyBase(object, ValueType::value_type())
525 {
526 flags |= Glib::PARAM_WRITABLE;
527 flags &= ~Glib::PARAM_READABLE;
528
529 if (!lookup_property(name))
530 install_property(static_cast<ValueType&>(value_).create_param_spec(name, nick, blurb, flags));
531
532 }
533
534 template <class T>
Property_WriteOnly(Glib::Object & object,const Glib::ustring & name,const PropertyType & default_value,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags)535 Property_WriteOnly<T>::Property_WriteOnly(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value,
536 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags)
537 : PropertyBase(object, ValueType::value_type())
538 {
539 flags |= Glib::PARAM_WRITABLE;
540 flags &= ~Glib::PARAM_READABLE;
541
542 static_cast<ValueType&>(value_).set(default_value);
543
544 if (!lookup_property(name))
545 install_property(static_cast<ValueType&>(value_).create_param_spec(name, nick, blurb, flags));
546 }
547
548 template <class T>
549 inline void
set_value(const typename Property_WriteOnly<T>::PropertyType & data)550 Property_WriteOnly<T>::set_value(const typename Property_WriteOnly<T>::PropertyType& data)
551 {
552 static_cast<ValueType&>(value_).set(data);
553 this->notify();
554 }
555
556 template <class T>
557 inline Property_WriteOnly<T>&
558 Property_WriteOnly<T>::operator=(const typename Property_WriteOnly<T>::PropertyType& data)
559 {
560 static_cast<ValueType&>(value_).set(data);
561 this->notify();
562 return *this;
563 }
564
565 template <class T>
566 inline Glib::PropertyProxy_WriteOnly<T>
get_proxy()567 Property_WriteOnly<T>::get_proxy()
568 {
569 return Glib::PropertyProxy_WriteOnly<T>(object_, get_name_internal());
570 }
571 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
572
573 } // namespace Glib
574
575 #endif /* _GLIBMM_PROPERTY_H */
576