Merge remote branch 'gvdb/master'
[platform/upstream/glib.git] / gobject / gbinding.c
1 /* gbinding.c: Binding for object properties
2  *
3  * Copyright (C) 2010  Intel Corp.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Emmanuele Bassi <ebassi@linux.intel.com>
21  */
22
23 /**
24  * SECTION:gbinding
25  * @Title: GBinding
26  * @Short_Description: Bind two object properties
27  *
28  * #GBinding is the representation of a binding between a property on a
29  * #GObject instance (or source) and another property on another #GObject
30  * instance (or target). Whenever the source property changes, the same
31  * value is applied to the target property; for instance, the following
32  * binding:
33  *
34  * |[
35  *   g_object_bind_property (object1, "property-a",
36  *                           object2, "property-b",
37  *                           G_BINDING_DEFAULT);
38  * ]|
39  *
40  * will cause <emphasis>object2:property-b</emphasis> to be updated every
41  * time g_object_set() or the specific accessor changes the value of
42  * <emphasis>object1:property-a</emphasis>.
43  *
44  * It is possible to create a bidirectional binding between two properties
45  * of two #GObject instances, so that if either property changes, the
46  * other is updated as well, for instance:
47  *
48  * |[
49  *   g_object_bind_property (object1, "property-a",
50  *                           object2, "property-b",
51  *                           G_BINDING_BIDIRECTIONAL);
52  * ]|
53  *
54  * will keep the two properties in sync.
55  *
56  * It is also possible to set a custom transformation function (in both
57  * directions, in case of a bidirectional binding) to apply a custom
58  * transformation from the source value to the target value before
59  * applying it; for instance, the following binding:
60  *
61  * |[
62  *   g_object_bind_property_full (adjustment1, "value",
63  *                                adjustment2, "value",
64  *                                G_BINDING_BIDIRECTIONAL,
65  *                                celsius_to_fahrenheit,
66  *                                fahrenheit_to_celsius,
67  *                                NULL, NULL);
68  * ]|
69  *
70  * will keep the <emphasis>value</emphasis> property of the two adjustments
71  * in sync; the <function>celsius_to_fahrenheit</function> function will be
72  * called whenever the <emphasis>adjustment1:value</emphasis> property changes
73  * and will transform the current value of the property before applying it
74  * to the <emphasis>adjustment2:value</emphasis> property; vice versa, the
75  * <function>fahrenheit_to_celsius</function> function will be called whenever
76  * the <emphasis>adjustment2:value</emphasis> property changes, and will
77  * transform the current value of the property before applying it to the
78  * <emphasis>adjustment1:value</emphasis>.
79  *
80  * Note that #GBinding does not resolve cycles by itself; a cycle like
81  *
82  * |[
83  *   object1:propertyA -> object2:propertyB
84  *   object2:propertyB -> object3:propertyC
85  *   object3:propertyC -> object1:propertyA
86  * ]|
87  *
88  * might lead to an infinite loop. The loop, in this particular case,
89  * can be avoided if the objects emit the #GObject::notify signal only
90  * if the value has effectively been changed. A binding is implemented
91  * using the #GObject::notify signal, so it is susceptible to all the
92  * various ways of blocking a signal emission, like g_signal_stop_emission()
93  * or g_signal_handler_block().
94  *
95  * A binding will be severed, and the resources it allocates freed, whenever
96  * either one of the #GObject instances it refers to are finalized, or when
97  * the #GBinding instance loses its last reference.
98  *
99  * #GBinding is available since GObject 2.26
100  */
101
102 #include "config.h"
103
104 #include <string.h>
105
106 #include "gbinding.h"
107 #include "genums.h"
108 #include "gmarshal.h"
109 #include "gobject.h"
110 #include "gsignal.h"
111 #include "gparamspecs.h"
112 #include "gvaluetypes.h"
113
114 #include "glibintl.h"
115
116
117 GType
118 g_binding_flags_get_type (void)
119 {
120   static volatile gsize g_define_type_id__volatile = 0;
121
122   if (g_once_init_enter (&g_define_type_id__volatile))
123     {
124       static const GFlagsValue values[] = {
125         { G_BINDING_DEFAULT, "G_BINDING_DEFAULT", "default" },
126         { G_BINDING_BIDIRECTIONAL, "G_BINDING_BIDIRECTIONAL", "bidirectional" },
127         { G_BINDING_SYNC_CREATE, "G_BINDING_SYNC_CREATE", "sync-create" },
128         { G_BINDING_INVERT_BOOLEAN, "G_BINDING_INVERT_BOOLEAN", "invert-boolean" },
129         { 0, NULL, NULL }
130       };
131       GType g_define_type_id =
132         g_flags_register_static (g_intern_static_string ("GBindingFlags"), values);
133       g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
134     }
135
136   return g_define_type_id__volatile;
137 }
138
139 #define G_BINDING_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_BINDING, GBindingClass))
140 #define G_IS_BINDING_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_BINDING))
141 #define G_BINDING_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_BINDING, GBindingClass))
142
143 typedef struct _GBindingClass           GBindingClass;
144
145 struct _GBinding
146 {
147   GObject parent_instance;
148
149   /* no reference is held on the objects, to avoid cycles */
150   GObject *source;
151   GObject *target;
152
153   /* the property names are interned, so they should not be freed */
154   gchar *source_property;
155   gchar *target_property;
156
157   GParamSpec *source_pspec;
158   GParamSpec *target_pspec;
159
160   GBindingTransformFunc transform_s2t;
161   GBindingTransformFunc transform_t2s;
162
163   GBindingFlags flags;
164
165   guint source_notify;
166   guint target_notify;
167
168   gpointer transform_data;
169   GDestroyNotify notify;
170
171   /* a guard, to avoid loops */
172   guint is_frozen : 1;
173 };
174
175 struct _GBindingClass
176 {
177   GObjectClass parent_class;
178 };
179
180 enum
181 {
182   PROP_0,
183
184   PROP_SOURCE,
185   PROP_TARGET,
186   PROP_SOURCE_PROPERTY,
187   PROP_TARGET_PROPERTY,
188   PROP_FLAGS
189 };
190
191 static GQuark quark_gbinding = 0;
192
193 G_DEFINE_TYPE (GBinding, g_binding, G_TYPE_OBJECT);
194
195 static inline void
196 add_binding_qdata (GObject  *gobject,
197                    GBinding *binding)
198 {
199   GHashTable *bindings;
200
201   bindings = g_object_get_qdata (gobject, quark_gbinding);
202   if (bindings == NULL)
203     {
204       bindings = g_hash_table_new (NULL, NULL);
205
206       g_object_set_qdata_full (gobject, quark_gbinding,
207                                bindings,
208                                (GDestroyNotify) g_hash_table_destroy);
209     }
210
211   g_hash_table_insert (bindings, binding, GUINT_TO_POINTER (1));
212 }
213
214 static inline void
215 remove_binding_qdata (GObject  *gobject,
216                       GBinding *binding)
217 {
218   GHashTable *bindings;
219
220   bindings = g_object_get_qdata (gobject, quark_gbinding);
221   g_hash_table_remove (bindings, binding);
222 }
223
224 /* the basic assumption is that if either the source or the target
225  * goes away then the binding does not exist any more and it should
226  * be reaped as well
227  */
228 static void
229 weak_unbind (gpointer  user_data,
230              GObject  *where_the_object_was)
231 {
232   GBinding *binding = user_data;
233
234   /* if what went away was the source, unset it so that GBinding::finalize
235    * does not try to access it; otherwise, disconnect everything and remove
236    * the GBinding instance from the object's qdata
237    */
238   if (binding->source == where_the_object_was)
239     binding->source = NULL;
240   else
241     {
242       if (binding->source_notify != 0)
243         g_signal_handler_disconnect (binding->source, binding->source_notify);
244
245       g_object_weak_unref (binding->source, weak_unbind, user_data);
246       remove_binding_qdata (binding->source, binding);
247       binding->source = NULL;
248     }
249
250   /* as above, but with the target */
251   if (binding->target == where_the_object_was)
252     binding->target = NULL;
253   else
254     {
255       if (binding->target_notify != 0)
256         g_signal_handler_disconnect (binding->target, binding->target_notify);
257
258       g_object_weak_unref (binding->target, weak_unbind, user_data);
259       remove_binding_qdata (binding->target, binding);
260       binding->target = NULL;
261     }
262
263   /* this will take care of the binding itself */
264   g_object_unref (binding);
265 }
266
267 static inline gboolean
268 default_transform (const GValue *value_a,
269                    GValue       *value_b)
270 {
271   /* if it's not the same type, try to convert it using the GValue
272    * transformation API; otherwise just copy it
273    */
274   if (!g_type_is_a (G_VALUE_TYPE (value_a), G_VALUE_TYPE (value_b)))
275     {
276       /* are these two types compatible (can be directly copied)? */
277       if (g_value_type_compatible (G_VALUE_TYPE (value_a),
278                                    G_VALUE_TYPE (value_b)))
279         {
280           g_value_copy (value_a, value_b);
281           goto done;
282         }
283
284       if (g_value_type_transformable (G_VALUE_TYPE (value_a),
285                                       G_VALUE_TYPE (value_b)))
286         {
287           if (g_value_transform (value_a, value_b))
288             goto done;
289
290           g_warning ("%s: Unable to convert a value of type %s to a "
291                      "value of type %s",
292                      G_STRLOC,
293                      g_type_name (G_VALUE_TYPE (value_a)),
294                      g_type_name (G_VALUE_TYPE (value_b)));
295
296           return FALSE;
297         }
298     }
299   else
300     g_value_copy (value_a, value_b);
301
302 done:
303   return TRUE;
304 }
305
306 static inline gboolean
307 default_invert_boolean_transform (const GValue *value_a,
308                                   GValue       *value_b)
309 {
310   gboolean value;
311
312   g_assert (G_VALUE_HOLDS_BOOLEAN (value_a));
313   g_assert (G_VALUE_HOLDS_BOOLEAN (value_b));
314
315   value = g_value_get_boolean (value_a);
316   value = !value;
317
318   g_value_set_boolean (value_b, value);
319
320   return TRUE;
321 }
322
323 static gboolean
324 default_transform_to (GBinding     *binding,
325                       const GValue *value_a,
326                       GValue       *value_b,
327                       gpointer      user_data G_GNUC_UNUSED)
328 {
329   if (binding->flags & G_BINDING_INVERT_BOOLEAN)
330     return default_invert_boolean_transform (value_a, value_b);
331
332   return default_transform (value_a, value_b);
333 }
334
335 static gboolean
336 default_transform_from (GBinding     *binding,
337                         const GValue *value_a,
338                         GValue       *value_b,
339                         gpointer      user_data G_GNUC_UNUSED)
340 {
341   if (binding->flags & G_BINDING_INVERT_BOOLEAN)
342     return default_invert_boolean_transform (value_a, value_b);
343
344   return default_transform (value_a, value_b);
345 }
346
347 static void
348 on_source_notify (GObject    *gobject,
349                   GParamSpec *pspec,
350                   GBinding   *binding)
351 {
352   const gchar *p_name;
353   GValue source_value = { 0, };
354   GValue target_value = { 0, };
355   gboolean res;
356
357   if (binding->is_frozen)
358     return;
359
360   p_name = g_intern_string (pspec->name);
361
362   if (p_name != binding->source_property)
363     return;
364
365   g_value_init (&source_value, G_PARAM_SPEC_VALUE_TYPE (binding->source_pspec));
366   g_value_init (&target_value, G_PARAM_SPEC_VALUE_TYPE (binding->target_pspec));
367
368   g_object_get_property (binding->source, binding->source_pspec->name, &source_value);
369
370   res = binding->transform_s2t (binding,
371                                 &source_value,
372                                 &target_value,
373                                 binding->transform_data);
374   if (res)
375     {
376       binding->is_frozen = TRUE;
377
378       g_param_value_validate (binding->target_pspec, &target_value);
379       g_object_set_property (binding->target, binding->target_pspec->name, &target_value);
380
381       binding->is_frozen = FALSE;
382     }
383
384   g_value_unset (&source_value);
385   g_value_unset (&target_value);
386 }
387
388 static void
389 on_target_notify (GObject    *gobject,
390                   GParamSpec *pspec,
391                   GBinding   *binding)
392 {
393   const gchar *p_name;
394   GValue source_value = { 0, };
395   GValue target_value = { 0, };
396   gboolean res;
397
398   if (binding->is_frozen)
399     return;
400
401   p_name = g_intern_string (pspec->name);
402
403   if (p_name != binding->target_property)
404     return;
405
406   g_value_init (&source_value, G_PARAM_SPEC_VALUE_TYPE (binding->target_pspec));
407   g_value_init (&target_value, G_PARAM_SPEC_VALUE_TYPE (binding->source_pspec));
408
409   g_object_get_property (binding->target, binding->target_pspec->name, &source_value);
410
411   res = binding->transform_t2s (binding,
412                                 &source_value,
413                                 &target_value,
414                                 binding->transform_data);
415   if (res)
416     {
417       binding->is_frozen = TRUE;
418
419       g_param_value_validate (binding->source_pspec, &target_value);
420       g_object_set_property (binding->source, binding->source_pspec->name, &target_value);
421
422       binding->is_frozen = FALSE;
423     }
424
425   g_value_unset (&source_value);
426   g_value_unset (&target_value);
427 }
428
429 static void
430 g_binding_finalize (GObject *gobject)
431 {
432   GBinding *binding = G_BINDING (gobject);
433
434   /* dispose of the transformation data */
435   if (binding->notify != NULL)
436     {
437       binding->notify (binding->transform_data);
438
439       binding->transform_data = NULL;
440       binding->notify = NULL;
441     }
442
443   /* we need this in case the source and target instance are still
444    * valid, and it was the GBinding that was unreferenced
445    */
446   if (binding->source != NULL)
447     {
448       if (binding->source_notify != 0)
449         g_signal_handler_disconnect (binding->source, binding->source_notify);
450
451       g_object_weak_unref (binding->source, weak_unbind, binding);
452       remove_binding_qdata (binding->source, binding);
453     }
454
455   if (binding->target != NULL)
456     {
457       if (binding->target_notify != 0)
458         g_signal_handler_disconnect (binding->target, binding->target_notify);
459
460       g_object_weak_unref (binding->target, weak_unbind, binding);
461       remove_binding_qdata (binding->target, binding);
462     }
463
464   G_OBJECT_CLASS (g_binding_parent_class)->finalize (gobject);
465 }
466
467 static void
468 g_binding_set_property (GObject      *gobject,
469                         guint         prop_id,
470                         const GValue *value,
471                         GParamSpec   *pspec)
472 {
473   GBinding *binding = G_BINDING (gobject);
474
475   switch (prop_id)
476     {
477     case PROP_SOURCE:
478       binding->source = g_value_get_object (value);
479       break;
480
481     case PROP_SOURCE_PROPERTY:
482       binding->source_property = g_intern_string (g_value_get_string (value));
483       break;
484
485     case PROP_TARGET:
486       binding->target = g_value_get_object (value);
487       break;
488
489     case PROP_TARGET_PROPERTY:
490       binding->target_property = g_intern_string (g_value_get_string (value));
491       break;
492
493     case PROP_FLAGS:
494       binding->flags = g_value_get_flags (value);
495       break;
496
497     default:
498       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
499       break;
500     }
501 }
502
503 static void
504 g_binding_get_property (GObject    *gobject,
505                         guint       prop_id,
506                         GValue     *value,
507                         GParamSpec *pspec)
508 {
509   GBinding *binding = G_BINDING (gobject);
510
511   switch (prop_id)
512     {
513     case PROP_SOURCE:
514       g_value_set_object (value, binding->source);
515       break;
516
517     case PROP_SOURCE_PROPERTY:
518       g_value_set_string (value, binding->source_property);
519       break;
520
521     case PROP_TARGET:
522       g_value_set_object (value, binding->target);
523       break;
524
525     case PROP_TARGET_PROPERTY:
526       g_value_set_string (value, binding->target_property);
527       break;
528
529     case PROP_FLAGS:
530       g_value_set_flags (value, binding->flags);
531       break;
532
533     default:
534       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
535       break;
536     }
537 }
538
539 static void
540 g_binding_constructed (GObject *gobject)
541 {
542   GBinding *binding = G_BINDING (gobject);
543
544   /* assert that we were constructed correctly */
545   g_assert (binding->source != NULL);
546   g_assert (binding->target != NULL);
547   g_assert (binding->source_property != NULL);
548   g_assert (binding->target_property != NULL);
549
550   /* we assume a check was performed prior to construction - since
551    * g_object_bind_property_full() does it; we cannot fail construction
552    * anyway, so it would be hard for use to properly warn here
553    */
554   binding->source_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (binding->source), binding->source_property);
555   binding->target_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (binding->target), binding->target_property);
556   g_assert (binding->source_pspec != NULL);
557   g_assert (binding->target_pspec != NULL);
558
559   /* set the default transformation functions here */
560   binding->transform_s2t = default_transform_to;
561   binding->transform_t2s = default_transform_from;
562
563   binding->transform_data = NULL;
564   binding->notify = NULL;
565
566   binding->source_notify = g_signal_connect (binding->source, "notify",
567                                              G_CALLBACK (on_source_notify),
568                                              binding);
569
570   g_object_weak_ref (binding->source, weak_unbind, binding);
571   add_binding_qdata (binding->source, binding);
572
573   if (binding->flags & G_BINDING_BIDIRECTIONAL)
574     binding->target_notify = g_signal_connect (binding->target, "notify",
575                                                G_CALLBACK (on_target_notify),
576                                                binding);
577
578   g_object_weak_ref (binding->target, weak_unbind, binding);
579   add_binding_qdata (binding->target, binding);
580
581 }
582
583 static void
584 g_binding_class_init (GBindingClass *klass)
585 {
586   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
587
588   quark_gbinding = g_quark_from_static_string ("g-binding");
589
590   gobject_class->constructed = g_binding_constructed;
591   gobject_class->set_property = g_binding_set_property;
592   gobject_class->get_property = g_binding_get_property;
593   gobject_class->finalize = g_binding_finalize;
594
595   /**
596    * GBinding:source:
597    *
598    * The #GObject that should be used as the source of the binding
599    *
600    * Since: 2.26
601    */
602   g_object_class_install_property (gobject_class, PROP_SOURCE,
603                                    g_param_spec_object ("source",
604                                                         P_("Source"),
605                                                         P_("The source of the binding"),
606                                                         G_TYPE_OBJECT,
607                                                         G_PARAM_CONSTRUCT_ONLY |
608                                                         G_PARAM_READWRITE |
609                                                         G_PARAM_STATIC_STRINGS));
610   /**
611    * GBinding:target:
612    *
613    * The #GObject that should be used as the target of the binding
614    *
615    * Since: 2.26
616    */
617   g_object_class_install_property (gobject_class, PROP_TARGET,
618                                    g_param_spec_object ("target",
619                                                         P_("Target"),
620                                                         P_("The target of the binding"),
621                                                         G_TYPE_OBJECT,
622                                                         G_PARAM_CONSTRUCT_ONLY |
623                                                         G_PARAM_READWRITE |
624                                                         G_PARAM_STATIC_STRINGS));
625   /**
626    * GBinding:source-property:
627    *
628    * The name of the property of #GBinding:source that should be used
629    * as the source of the binding
630    *
631    * Since: 2.26
632    */
633   g_object_class_install_property (gobject_class, PROP_SOURCE_PROPERTY,
634                                    g_param_spec_string ("source-property",
635                                                         P_("Source Property"),
636                                                         P_("The property on the source to bind"),
637                                                         NULL,
638                                                         G_PARAM_CONSTRUCT_ONLY |
639                                                         G_PARAM_READWRITE |
640                                                         G_PARAM_STATIC_STRINGS));
641   /**
642    * GBinding:target-property:
643    *
644    * The name of the property of #GBinding:target that should be used
645    * as the target of the binding
646    *
647    * Since: 2.26
648    */
649   g_object_class_install_property (gobject_class, PROP_TARGET_PROPERTY,
650                                    g_param_spec_string ("target-property",
651                                                         P_("Target Property"),
652                                                         P_("The property on the target to bind"),
653                                                         NULL,
654                                                         G_PARAM_CONSTRUCT_ONLY |
655                                                         G_PARAM_READWRITE |
656                                                         G_PARAM_STATIC_STRINGS));
657   /**
658    * GBinding:flags:
659    *
660    * Flags to be used to control the #GBinding
661    *
662    * Since: 2.26
663    */
664   g_object_class_install_property (gobject_class, PROP_FLAGS,
665                                    g_param_spec_flags ("flags",
666                                                        P_("Flags"),
667                                                        P_("The binding flags"),
668                                                        G_TYPE_BINDING_FLAGS,
669                                                        G_BINDING_DEFAULT,
670                                                        G_PARAM_CONSTRUCT_ONLY |
671                                                        G_PARAM_READWRITE |
672                                                        G_PARAM_STATIC_STRINGS));
673 }
674
675 static void
676 g_binding_init (GBinding *binding)
677 {
678 }
679
680 /**
681  * g_binding_get_flags:
682  * @binding: a #GBinding
683  *
684  * Retrieves the flags passed when constructing the #GBinding
685  *
686  * Return value: the #GBindingFlags used by the #GBinding
687  *
688  * Since: 2.26
689  */
690 GBindingFlags
691 g_binding_get_flags (GBinding *binding)
692 {
693   g_return_val_if_fail (G_IS_BINDING (binding), G_BINDING_DEFAULT);
694
695   return binding->flags;
696 }
697
698 /**
699  * g_binding_get_source:
700  * @binding: a #GBinding
701  *
702  * Retrieves the #GObject instance used as the source of the binding
703  *
704  * Return value: (transfer none): the source #GObject
705  *
706  * Since: 2.26
707  */
708 GObject *
709 g_binding_get_source (GBinding *binding)
710 {
711   g_return_val_if_fail (G_IS_BINDING (binding), NULL);
712
713   return binding->source;
714 }
715
716 /**
717  * g_binding_get_target:
718  * @binding: a #GBinding
719  *
720  * Retrieves the #GObject instance used as the target of the binding
721  *
722  * Return value: (transfer none): the target #GObject
723  *
724  * Since: 2.26
725  */
726 GObject *
727 g_binding_get_target (GBinding *binding)
728 {
729   g_return_val_if_fail (G_IS_BINDING (binding), NULL);
730
731   return binding->target;
732 }
733
734 /**
735  * g_binding_get_source_property:
736  * @binding: a #GBinding
737  *
738  * Retrieves the name of the property of #GBinding:source used as the source
739  * of the binding
740  *
741  * Return value: the name of the source property
742  *
743  * Since: 2.26
744  */
745 G_CONST_RETURN gchar *
746 g_binding_get_source_property (GBinding *binding)
747 {
748   g_return_val_if_fail (G_IS_BINDING (binding), NULL);
749
750   return binding->source_property;
751 }
752
753 /**
754  * g_binding_get_target_property:
755  * @binding: a #GBinding
756  *
757  * Retrieves the name of the property of #GBinding:target used as the target
758  * of the binding
759  *
760  * Return value: the name of the target property
761  *
762  * Since: 2.26
763  */
764 G_CONST_RETURN gchar *
765 g_binding_get_target_property (GBinding *binding)
766 {
767   g_return_val_if_fail (G_IS_BINDING (binding), NULL);
768
769   return binding->target_property;
770 }
771
772 /**
773  * g_object_bind_property_full:
774  * @source: the source #GObject
775  * @source_property: the property on @source to bind
776  * @target: the target #GObject
777  * @target_property: the property on @target to bind
778  * @flags: flags to pass to #GBinding
779  * @transform_to: (scope notified) (allow-none): the transformation function
780  *   from the @source to the @target, or %NULL to use the default
781  * @transform_from: (scope notified) (allow-none): the transformation function
782  *   from the @target to the @source, or %NULL to use the default
783  * @user_data: custom data to be passed to the transformation functions,
784  *   or %NULL
785  * @notify: function to be called when disposing the binding, to free the
786  *   resources used by the transformation functions
787  *
788  * Complete version of g_object_bind_property().
789  *
790  * Creates a binding between @source_property on @source and @target_property
791  * on @target, allowing you to set the transformation functions to be used by
792  * the binding.
793  *
794  * If @flags contains %G_BINDING_BIDIRECTIONAL then the binding will be mutual:
795  * if @target_property on @target changes then the @source_property on @source
796  * will be updated as well. The @transform_from function is only used in case
797  * of bidirectional bindings, otherwise it will be ignored
798  *
799  * The binding will automatically be removed when either the @source or the
800  * @target instances are finalized. To remove the binding without affecting the
801  * @source and the @target you can just call g_object_unref() on the returned
802  * #GBinding instance.
803  *
804  * A #GObject can have multiple bindings.
805  *
806  * <note>The same @user_data parameter will be used for both @transform_to
807  * and @transform_from transformation functions; the @notify function will
808  * be called once, when the binding is removed. If you need different data
809  * for each transformation function, please use
810  * g_object_bind_property_with_closures() instead.</note>
811  *
812  * Return value: (transfer none): the #GBinding instance representing the
813  *   binding between the two #GObject instances. The binding is released
814  *   whenever the #GBinding reference count reaches zero.
815  *
816  * Since: 2.26
817  */
818 GBinding *
819 g_object_bind_property_full (gpointer               source,
820                              const gchar           *source_property,
821                              gpointer               target,
822                              const gchar           *target_property,
823                              GBindingFlags          flags,
824                              GBindingTransformFunc  transform_to,
825                              GBindingTransformFunc  transform_from,
826                              gpointer               user_data,
827                              GDestroyNotify         notify)
828 {
829   GParamSpec *pspec;
830   GBinding *binding;
831
832   g_return_val_if_fail (G_IS_OBJECT (source), NULL);
833   g_return_val_if_fail (source_property != NULL, NULL);
834   g_return_val_if_fail (G_IS_OBJECT (target), NULL);
835   g_return_val_if_fail (target_property != NULL, NULL);
836
837   if (source == target && g_strcmp0 (source_property, target_property) == 0)
838     {
839       g_warning ("Unable to bind the same property on the same instance");
840       return NULL;
841     }
842
843   /* remove the G_BINDING_INVERT_BOOLEAN flag in case we have
844    * custom transformation functions
845    */
846   if ((flags & G_BINDING_INVERT_BOOLEAN) &&
847       (transform_to != NULL || transform_from != NULL))
848     {
849       flags &= ~G_BINDING_INVERT_BOOLEAN;
850     }
851
852   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (source), source_property);
853   if (pspec == NULL)
854     {
855       g_warning ("%s: The source object of type %s has no property called '%s'",
856                  G_STRLOC,
857                  G_OBJECT_TYPE_NAME (source),
858                  source_property);
859       return NULL;
860     }
861
862   if (!(pspec->flags & G_PARAM_READABLE))
863     {
864       g_warning ("%s: The source object of type %s has no readable property called '%s'",
865                  G_STRLOC,
866                  G_OBJECT_TYPE_NAME (source),
867                  source_property);
868       return NULL;
869     }
870
871   if ((flags & G_BINDING_BIDIRECTIONAL) &&
872       ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) || !(pspec->flags & G_PARAM_WRITABLE)))
873     {
874       g_warning ("%s: The source object of type %s has no writable property called '%s'",
875                  G_STRLOC,
876                  G_OBJECT_TYPE_NAME (source),
877                  source_property);
878       return NULL;
879     }
880
881   if ((flags & G_BINDING_INVERT_BOOLEAN) &&
882       !(G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN))
883     {
884       g_warning ("%s: The G_BINDING_INVERT_BOOLEAN flag can only be used "
885                  "when binding boolean properties; the source property '%s' "
886                  "is of type '%s'",
887                  G_STRLOC,
888                  source_property,
889                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
890       return NULL;
891     }
892
893   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), target_property);
894   if (pspec == NULL)
895     {
896       g_warning ("%s: The target object of type %s has no property called '%s'",
897                  G_STRLOC,
898                  G_OBJECT_TYPE_NAME (target),
899                  target_property);
900       return NULL;
901     }
902
903   if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) || !(pspec->flags & G_PARAM_WRITABLE))
904     {
905       g_warning ("%s: The target object of type %s has no writable property called '%s'",
906                  G_STRLOC,
907                  G_OBJECT_TYPE_NAME (target),
908                  target_property);
909       return NULL;
910     }
911
912   if ((flags & G_BINDING_BIDIRECTIONAL) &&
913       !(pspec->flags & G_PARAM_READABLE))
914     {
915       g_warning ("%s: The starget object of type %s has no writable property called '%s'",
916                  G_STRLOC,
917                  G_OBJECT_TYPE_NAME (target),
918                  target_property);
919       return NULL;
920     }
921
922   if ((flags & G_BINDING_INVERT_BOOLEAN) &&
923       !(G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN))
924     {
925       g_warning ("%s: The G_BINDING_INVERT_BOOLEAN flag can only be used "
926                  "when binding boolean properties; the target property '%s' "
927                  "is of type '%s'",
928                  G_STRLOC,
929                  target_property,
930                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
931       return NULL;
932     }
933
934   binding = g_object_new (G_TYPE_BINDING,
935                           "source", source,
936                           "source-property", source_property,
937                           "target", target,
938                           "target-property", target_property,
939                           "flags", flags,
940                           NULL);
941
942   if (transform_to != NULL)
943     binding->transform_s2t = transform_to;
944
945   if (transform_from != NULL)
946     binding->transform_t2s = transform_from;
947
948   binding->transform_data = user_data;
949   binding->notify = notify;
950
951   /* synchronize the target with the source by faking an emission of
952    * the ::notify signal for the source property; this will also take
953    * care of the bidirectional binding case because the eventual change
954    * will emit a notification on the target
955    */
956   if (flags & G_BINDING_SYNC_CREATE)
957     on_source_notify (binding->source, binding->source_pspec, binding);
958
959   return binding;
960 }
961
962 /**
963  * g_object_bind_property:
964  * @source: the source #GObject
965  * @source_property: the property on @source to bind
966  * @target: the target #GObject
967  * @target_property: the property on @target to bind
968  * @flags: flags to pass to #GBinding
969  *
970  * Creates a binding between @source_property on @source and @target_property
971  * on @target. Whenever the @source_property is changed the @target_property is
972  * updated using the same value. For instance:
973  *
974  * |[
975  *   g_object_bind_property (action, "active", widget, "sensitive", 0);
976  * ]|
977  *
978  * Will result in the "sensitive" property of the widget #GObject instance to be
979  * updated with the same value of the "active" property of the action #GObject
980  * instance.
981  *
982  * If @flags contains %G_BINDING_BIDIRECTIONAL then the binding will be mutual:
983  * if @target_property on @target changes then the @source_property on @source
984  * will be updated as well.
985  *
986  * The binding will automatically be removed when either the @source or the
987  * @target instances are finalized. To remove the binding without affecting the
988  * @source and the @target you can just call g_object_unref() on the returned
989  * #GBinding instance.
990  *
991  * A #GObject can have multiple bindings.
992  *
993  * Return value: (transfer none): the #GBinding instance representing the
994  *   binding between the two #GObject instances. The binding is released
995  *   whenever the #GBinding reference count reaches zero.
996  *
997  * Since: 2.26
998  */
999 GBinding *
1000 g_object_bind_property (gpointer       source,
1001                         const gchar   *source_property,
1002                         gpointer       target,
1003                         const gchar   *target_property,
1004                         GBindingFlags  flags)
1005 {
1006   /* type checking is done in g_object_bind_property_full() */
1007
1008   return g_object_bind_property_full (source, source_property,
1009                                       target, target_property,
1010                                       flags,
1011                                       NULL,
1012                                       NULL,
1013                                       NULL, NULL);
1014 }
1015
1016 typedef struct _TransformData
1017 {
1018   GClosure *transform_to_closure;
1019   GClosure *transform_from_closure;
1020 } TransformData;
1021
1022 static gboolean
1023 bind_with_closures_transform_to (GBinding     *binding,
1024                                  const GValue *source,
1025                                  GValue       *target,
1026                                  gpointer      data)
1027 {
1028   TransformData *t_data = data;
1029   GValue params[3] = { { 0, }, { 0, }, { 0, } };
1030   GValue retval = { 0, };
1031   gboolean res;
1032
1033   g_value_init (&params[0], G_TYPE_BINDING);
1034   g_value_set_object (&params[0], binding);
1035
1036   g_value_init (&params[1], G_TYPE_VALUE);
1037   g_value_set_boxed (&params[1], source);
1038
1039   g_value_init (&params[2], G_TYPE_VALUE);
1040   g_value_set_boxed (&params[2], target);
1041
1042   g_value_init (&retval, G_TYPE_BOOLEAN);
1043   g_value_set_boolean (&retval, FALSE);
1044
1045   g_closure_invoke (t_data->transform_to_closure, &retval, 3, params, NULL);
1046
1047   res = g_value_get_boolean (&retval);
1048   if (res)
1049     {
1050       const GValue *out_value = g_value_get_boxed (&params[2]);
1051
1052       g_assert (out_value != NULL);
1053
1054       g_value_copy (out_value, target);
1055     }
1056
1057   g_value_unset (&params[0]);
1058   g_value_unset (&params[1]);
1059   g_value_unset (&params[2]);
1060   g_value_unset (&retval);
1061
1062   return res;
1063 }
1064
1065 static gboolean
1066 bind_with_closures_transform_from (GBinding     *binding,
1067                                    const GValue *source,
1068                                    GValue       *target,
1069                                    gpointer      data)
1070 {
1071   TransformData *t_data = data;
1072   GValue params[3] = { { 0, }, { 0, }, { 0, } };
1073   GValue retval = { 0, };
1074   gboolean res;
1075
1076   g_value_init (&params[0], G_TYPE_BINDING);
1077   g_value_set_object (&params[0], binding);
1078
1079   g_value_init (&params[1], G_TYPE_VALUE);
1080   g_value_set_boxed (&params[1], source);
1081
1082   g_value_init (&params[2], G_TYPE_VALUE);
1083   g_value_set_boxed (&params[2], target);
1084
1085   g_value_init (&retval, G_TYPE_BOOLEAN);
1086   g_value_set_boolean (&retval, FALSE);
1087
1088   g_closure_invoke (t_data->transform_from_closure, &retval, 3, params, NULL);
1089
1090   res = g_value_get_boolean (&retval);
1091   if (res)
1092     {
1093       const GValue *out_value = g_value_get_boxed (&params[2]);
1094
1095       g_assert (out_value != NULL);
1096
1097       g_value_copy (out_value, target);
1098     }
1099
1100   g_value_unset (&params[0]);
1101   g_value_unset (&params[1]);
1102   g_value_unset (&params[2]);
1103   g_value_unset (&retval);
1104
1105   return res;
1106 }
1107
1108 static void
1109 bind_with_closures_free_func (gpointer data)
1110 {
1111   TransformData *t_data = data;
1112
1113   if (t_data->transform_to_closure != NULL)
1114     g_closure_unref (t_data->transform_to_closure);
1115
1116   if (t_data->transform_from_closure != NULL)
1117     g_closure_unref (t_data->transform_from_closure);
1118
1119   g_slice_free (TransformData, t_data);
1120 }
1121
1122 /**
1123  * g_object_bind_property_with_closures:
1124  * @source: the source #GObject
1125  * @source_property: the property on @source to bind
1126  * @target: the target #GObject
1127  * @target_property: the property on @target to bind
1128  * @flags: flags to pass to #GBinding
1129  * @transform_to: a #GClosure wrapping the transformation function
1130  *   from the @source to the @target, or %NULL to use the default
1131  * @transform_from: a #GClosure wrapping the transformation function
1132  *   from the @target to the @source, or %NULL to use the default
1133  *
1134  * Creates a binding between @source_property on @source and @target_property
1135  * on @target, allowing you to set the transformation functions to be used by
1136  * the binding.
1137  *
1138  * This function is the language bindings friendly version of
1139  * g_object_bind_property_full(), using #GClosure<!-- -->s instead of
1140  * function pointers.
1141  *
1142  * Rename to: g_object_bind_property_full
1143  *
1144  * Return value: (transfer none): the #GBinding instance representing the
1145  *   binding between the two #GObject instances. The binding is released
1146  *   whenever the #GBinding reference count reaches zero.
1147  *
1148  * Since: 2.26
1149  */
1150 GBinding *
1151 g_object_bind_property_with_closures (gpointer       source,
1152                                       const gchar   *source_property,
1153                                       gpointer       target,
1154                                       const gchar   *target_property,
1155                                       GBindingFlags  flags,
1156                                       GClosure      *transform_to,
1157                                       GClosure      *transform_from)
1158 {
1159   TransformData *data;
1160
1161   data = g_slice_new0 (TransformData);
1162
1163   if (transform_to != NULL)
1164     {
1165       if (G_CLOSURE_NEEDS_MARSHAL (transform_to))
1166         g_closure_set_marshal (transform_to, g_cclosure_marshal_BOOLEAN__BOXED_BOXED);
1167
1168       data->transform_to_closure = g_closure_ref (transform_to);
1169       g_closure_sink (data->transform_to_closure);
1170     }
1171
1172   if (transform_from != NULL)
1173     {
1174       if (G_CLOSURE_NEEDS_MARSHAL (transform_from))
1175         g_closure_set_marshal (transform_from, g_cclosure_marshal_BOOLEAN__BOXED_BOXED);
1176
1177       data->transform_from_closure = g_closure_ref (transform_from);
1178       g_closure_sink (data->transform_from_closure);
1179     }
1180
1181   return g_object_bind_property_full (source, source_property,
1182                                       target, target_property,
1183                                       flags,
1184                                       transform_to != NULL ? bind_with_closures_transform_to : NULL,
1185                                       transform_from != NULL ? bind_with_closures_transform_from : NULL,
1186                                       data,
1187                                       bind_with_closures_free_func);
1188 }