Branch data Line data Source code
1 : : /* GObject - GLib Type, Object, Parameter and Signal Library
2 : : *
3 : : * Copyright (C) 2015-2022 Christian Hergert <christian@hergert.me>
4 : : * Copyright (C) 2015 Garrett Regier <garrettregier@gmail.com>
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
17 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : * SPDX-License-Identifier: LGPL-2.1-or-later
20 : : */
21 : :
22 : : #include "config.h"
23 : : #include "glib.h"
24 : : #include "glibintl.h"
25 : :
26 : : #include "gbindinggroup.h"
27 : : #include "gparamspecs.h"
28 : :
29 : : /**
30 : : * GBindingGroup:
31 : : *
32 : : * `GBindingGroup` can be used to bind multiple properties
33 : : * from an object collectively.
34 : : *
35 : : * Use the various methods to bind properties from a single source
36 : : * object to multiple destination objects. Properties can be bound
37 : : * bidirectionally and are connected when the source object is set
38 : : * with [method@GObject.BindingGroup.set_source].
39 : : *
40 : : * Since: 2.72
41 : : */
42 : :
43 : : #if 0
44 : : # define DEBUG_BINDINGS
45 : : #endif
46 : :
47 : : struct _GBindingGroup
48 : : {
49 : : GObject parent_instance;
50 : : GMutex mutex;
51 : : GObject *source; /* (owned weak) */
52 : : GPtrArray *lazy_bindings; /* (owned) (element-type LazyBinding) */
53 : : };
54 : :
55 : : typedef struct _GBindingGroupClass
56 : : {
57 : : GObjectClass parent_class;
58 : : } GBindingGroupClass;
59 : :
60 : : typedef struct
61 : : {
62 : : GBindingGroup *group; /* (unowned) */
63 : : const char *source_property; /* (interned) */
64 : : const char *target_property; /* (interned) */
65 : : GObject *target; /* (owned weak) */
66 : : GBinding *binding; /* (unowned) */
67 : : gpointer user_data;
68 : : GDestroyNotify user_data_destroy;
69 : : gpointer transform_to; /* (nullable) (owned) */
70 : : gpointer transform_from; /* (nullable) (owned) */
71 : : GBindingFlags binding_flags;
72 : : guint using_closures : 1;
73 : : } LazyBinding;
74 : :
75 : 164 : G_DEFINE_TYPE (GBindingGroup, g_binding_group, G_TYPE_OBJECT)
76 : :
77 : : typedef enum
78 : : {
79 : : PROP_SOURCE = 1,
80 : : N_PROPS
81 : : } GBindingGroupProperty;
82 : :
83 : : static void lazy_binding_free (gpointer data);
84 : :
85 : : static GParamSpec *properties[N_PROPS];
86 : :
87 : : static void
88 : 38 : g_binding_group_connect (GBindingGroup *self,
89 : : LazyBinding *lazy_binding)
90 : : {
91 : : GBinding *binding;
92 : :
93 : 38 : g_assert (G_IS_BINDING_GROUP (self));
94 : 38 : g_assert (self->source != NULL);
95 : 38 : g_assert (lazy_binding != NULL);
96 : 38 : g_assert (lazy_binding->binding == NULL);
97 : 38 : g_assert (lazy_binding->target != NULL);
98 : 38 : g_assert (lazy_binding->target_property != NULL);
99 : 38 : g_assert (lazy_binding->source_property != NULL);
100 : :
101 : : #ifdef DEBUG_BINDINGS
102 : : {
103 : : GFlagsClass *flags_class;
104 : : g_autofree gchar *flags_str = NULL;
105 : :
106 : : flags_class = g_type_class_ref (G_TYPE_BINDING_FLAGS);
107 : : flags_str = g_flags_to_string (flags_class, lazy_binding->binding_flags);
108 : :
109 : : g_print ("Binding %s(%p):%s to %s(%p):%s (flags=%s)\n",
110 : : G_OBJECT_TYPE_NAME (self->source),
111 : : self->source,
112 : : lazy_binding->source_property,
113 : : G_OBJECT_TYPE_NAME (lazy_binding->target),
114 : : lazy_binding->target,
115 : : lazy_binding->target_property,
116 : : flags_str);
117 : :
118 : : g_type_class_unref (flags_class);
119 : : }
120 : : #endif
121 : :
122 : 38 : if (!lazy_binding->using_closures)
123 : 37 : binding = g_object_bind_property_full (self->source,
124 : 37 : lazy_binding->source_property,
125 : 37 : lazy_binding->target,
126 : 37 : lazy_binding->target_property,
127 : : lazy_binding->binding_flags,
128 : 37 : lazy_binding->transform_to,
129 : 37 : lazy_binding->transform_from,
130 : : lazy_binding->user_data,
131 : : NULL);
132 : : else
133 : 1 : binding = g_object_bind_property_with_closures (self->source,
134 : 1 : lazy_binding->source_property,
135 : 1 : lazy_binding->target,
136 : 1 : lazy_binding->target_property,
137 : : lazy_binding->binding_flags,
138 : 1 : lazy_binding->transform_to,
139 : 1 : lazy_binding->transform_from);
140 : :
141 : 38 : lazy_binding->binding = binding;
142 : 38 : }
143 : :
144 : : static void
145 : 43 : g_binding_group_disconnect (LazyBinding *lazy_binding)
146 : : {
147 : 43 : g_assert (lazy_binding != NULL);
148 : :
149 : 43 : if (lazy_binding->binding != NULL)
150 : : {
151 : 35 : g_binding_unbind (lazy_binding->binding);
152 : 35 : lazy_binding->binding = NULL;
153 : : }
154 : 43 : }
155 : :
156 : : static void
157 : 4 : g_binding_group__source_weak_notify (gpointer data,
158 : : GObject *where_object_was)
159 : : {
160 : 4 : GBindingGroup *self = data;
161 : : guint i;
162 : :
163 : 4 : g_assert (G_IS_BINDING_GROUP (self));
164 : :
165 : 4 : g_mutex_lock (&self->mutex);
166 : :
167 : 4 : self->source = NULL;
168 : :
169 : 5 : for (i = 0; i < self->lazy_bindings->len; i++)
170 : : {
171 : 1 : LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
172 : :
173 : 1 : lazy_binding->binding = NULL;
174 : : }
175 : :
176 : 4 : g_mutex_unlock (&self->mutex);
177 : 4 : }
178 : :
179 : : static void
180 : 5 : g_binding_group__target_weak_notify (gpointer data,
181 : : GObject *where_object_was)
182 : : {
183 : 5 : GBindingGroup *self = data;
184 : 5 : LazyBinding *to_free = NULL;
185 : : guint i;
186 : :
187 : 5 : g_assert (G_IS_BINDING_GROUP (self));
188 : :
189 : 5 : g_mutex_lock (&self->mutex);
190 : :
191 : 5 : for (i = 0; i < self->lazy_bindings->len; i++)
192 : : {
193 : 5 : LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
194 : :
195 : 5 : if (lazy_binding->target == where_object_was)
196 : : {
197 : 5 : lazy_binding->target = NULL;
198 : 5 : lazy_binding->binding = NULL;
199 : :
200 : 5 : to_free = g_ptr_array_steal_index_fast (self->lazy_bindings, i);
201 : 5 : break;
202 : : }
203 : : }
204 : :
205 : 5 : g_mutex_unlock (&self->mutex);
206 : :
207 : 5 : if (to_free != NULL)
208 : 5 : lazy_binding_free (to_free);
209 : 5 : }
210 : :
211 : : static void
212 : 18 : lazy_binding_free (gpointer data)
213 : : {
214 : 18 : LazyBinding *lazy_binding = data;
215 : :
216 : 18 : if (lazy_binding->target != NULL)
217 : : {
218 : 13 : g_object_weak_unref (lazy_binding->target,
219 : : g_binding_group__target_weak_notify,
220 : 13 : lazy_binding->group);
221 : 13 : lazy_binding->target = NULL;
222 : : }
223 : :
224 : 18 : g_binding_group_disconnect (lazy_binding);
225 : :
226 : 18 : lazy_binding->group = NULL;
227 : 18 : lazy_binding->source_property = NULL;
228 : 18 : lazy_binding->target_property = NULL;
229 : :
230 : 18 : if (lazy_binding->user_data_destroy)
231 : 1 : lazy_binding->user_data_destroy (lazy_binding->user_data);
232 : :
233 : 18 : if (lazy_binding->using_closures)
234 : : {
235 : 1 : g_clear_pointer (&lazy_binding->transform_to, g_closure_unref);
236 : 1 : g_clear_pointer (&lazy_binding->transform_from, g_closure_unref);
237 : : }
238 : :
239 : 18 : g_slice_free (LazyBinding, lazy_binding);
240 : 18 : }
241 : :
242 : : static void
243 : 12 : g_binding_group_dispose (GObject *object)
244 : : {
245 : 12 : GBindingGroup *self = (GBindingGroup *)object;
246 : 12 : LazyBinding **lazy_bindings = NULL;
247 : 12 : gsize len = 0;
248 : : gsize i;
249 : :
250 : 12 : g_assert (G_IS_BINDING_GROUP (self));
251 : :
252 : 12 : g_mutex_lock (&self->mutex);
253 : :
254 : 12 : if (self->source != NULL)
255 : : {
256 : 2 : g_object_weak_unref (self->source,
257 : : g_binding_group__source_weak_notify,
258 : : self);
259 : 2 : self->source = NULL;
260 : : }
261 : :
262 : 12 : if (self->lazy_bindings->len > 0)
263 : 5 : lazy_bindings = (LazyBinding **)g_ptr_array_steal (self->lazy_bindings, &len);
264 : :
265 : 12 : g_mutex_unlock (&self->mutex);
266 : :
267 : : /* Free bindings without holding self->mutex to avoid re-entrancy
268 : : * from collateral damage through release of binding closure data,
269 : : * GDataList, etc.
270 : : */
271 : 25 : for (i = 0; i < len; i++)
272 : 13 : lazy_binding_free (lazy_bindings[i]);
273 : 12 : g_free (lazy_bindings);
274 : :
275 : 12 : G_OBJECT_CLASS (g_binding_group_parent_class)->dispose (object);
276 : 12 : }
277 : :
278 : : static void
279 : 12 : g_binding_group_finalize (GObject *object)
280 : : {
281 : 12 : GBindingGroup *self = (GBindingGroup *)object;
282 : :
283 : 12 : g_assert (self->lazy_bindings != NULL);
284 : 12 : g_assert (self->lazy_bindings->len == 0);
285 : :
286 : 12 : g_clear_pointer (&self->lazy_bindings, g_ptr_array_unref);
287 : 12 : g_mutex_clear (&self->mutex);
288 : :
289 : 12 : G_OBJECT_CLASS (g_binding_group_parent_class)->finalize (object);
290 : 12 : }
291 : :
292 : : static void
293 : 3 : g_binding_group_get_property (GObject *object,
294 : : guint prop_id,
295 : : GValue *value,
296 : : GParamSpec *pspec)
297 : : {
298 : 3 : GBindingGroup *self = G_BINDING_GROUP (object);
299 : :
300 : 3 : switch ((GBindingGroupProperty) prop_id)
301 : : {
302 : 3 : case PROP_SOURCE:
303 : 3 : g_value_take_object (value, g_binding_group_dup_source (self));
304 : 3 : break;
305 : :
306 : 0 : default:
307 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
308 : : }
309 : 3 : }
310 : :
311 : : static void
312 : 1 : g_binding_group_set_property (GObject *object,
313 : : guint prop_id,
314 : : const GValue *value,
315 : : GParamSpec *pspec)
316 : : {
317 : 1 : GBindingGroup *self = G_BINDING_GROUP (object);
318 : :
319 : 1 : switch ((GBindingGroupProperty) prop_id)
320 : : {
321 : 1 : case PROP_SOURCE:
322 : 1 : g_binding_group_set_source (self, g_value_get_object (value));
323 : 1 : break;
324 : :
325 : 0 : default:
326 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
327 : : }
328 : 1 : }
329 : :
330 : : static void
331 : 3 : g_binding_group_class_init (GBindingGroupClass *klass)
332 : : {
333 : 3 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
334 : :
335 : 3 : object_class->dispose = g_binding_group_dispose;
336 : 3 : object_class->finalize = g_binding_group_finalize;
337 : 3 : object_class->get_property = g_binding_group_get_property;
338 : 3 : object_class->set_property = g_binding_group_set_property;
339 : :
340 : : /**
341 : : * GBindingGroup:source:
342 : : *
343 : : * The source object used for binding properties.
344 : : *
345 : : * Since: 2.72
346 : : */
347 : 3 : properties[PROP_SOURCE] =
348 : 3 : g_param_spec_object ("source", NULL, NULL,
349 : : G_TYPE_OBJECT,
350 : : (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
351 : :
352 : 3 : g_object_class_install_properties (object_class, N_PROPS, properties);
353 : 3 : }
354 : :
355 : : static void
356 : 12 : g_binding_group_init (GBindingGroup *self)
357 : : {
358 : 12 : g_mutex_init (&self->mutex);
359 : 12 : self->lazy_bindings = g_ptr_array_new_with_free_func (lazy_binding_free);
360 : 12 : }
361 : :
362 : : /**
363 : : * g_binding_group_new:
364 : : *
365 : : * Creates a new #GBindingGroup.
366 : : *
367 : : * Returns: (transfer full): a new #GBindingGroup
368 : : *
369 : : * Since: 2.72
370 : : */
371 : : GBindingGroup *
372 : 11 : g_binding_group_new (void)
373 : : {
374 : 11 : return g_object_new (G_TYPE_BINDING_GROUP, NULL);
375 : : }
376 : :
377 : : /**
378 : : * g_binding_group_dup_source:
379 : : * @self: the #GBindingGroup
380 : : *
381 : : * Gets the source object used for binding properties.
382 : : *
383 : : * Returns: (transfer none) (nullable) (type GObject): a #GObject or %NULL.
384 : : *
385 : : * Since: 2.72
386 : : */
387 : : gpointer
388 : 17 : g_binding_group_dup_source (GBindingGroup *self)
389 : : {
390 : : GObject *source;
391 : :
392 : 17 : g_return_val_if_fail (G_IS_BINDING_GROUP (self), NULL);
393 : :
394 : 17 : g_mutex_lock (&self->mutex);
395 : 17 : source = self->source ? g_object_ref (self->source) : NULL;
396 : 17 : g_mutex_unlock (&self->mutex);
397 : :
398 : 17 : return source;
399 : : }
400 : :
401 : : static gboolean
402 : 17 : g_binding_group_check_source (GBindingGroup *self,
403 : : gpointer source)
404 : : {
405 : : guint i;
406 : :
407 : 17 : g_assert (G_IS_BINDING_GROUP (self));
408 : 17 : g_assert (!source || G_IS_OBJECT (source));
409 : :
410 : 49 : for (i = 0; i < self->lazy_bindings->len; i++)
411 : : {
412 : 33 : LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
413 : :
414 : 33 : g_return_val_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
415 : : lazy_binding->source_property) != NULL,
416 : : FALSE);
417 : : }
418 : :
419 : 16 : return TRUE;
420 : : }
421 : :
422 : : /**
423 : : * g_binding_group_set_source:
424 : : * @self: the #GBindingGroup
425 : : * @source: (type GObject) (nullable) (transfer none): the source #GObject,
426 : : * or %NULL to clear it
427 : : *
428 : : * Sets @source as the source object used for creating property
429 : : * bindings. If there is already a source object all bindings from it
430 : : * will be removed.
431 : : *
432 : : * Note that all properties that have been bound must exist on @source.
433 : : *
434 : : * Since: 2.72
435 : : */
436 : : void
437 : 28 : g_binding_group_set_source (GBindingGroup *self,
438 : : gpointer source)
439 : : {
440 : 28 : gboolean notify = FALSE;
441 : :
442 : 28 : g_return_if_fail (G_IS_BINDING_GROUP (self));
443 : 28 : g_return_if_fail (!source || G_IS_OBJECT (source));
444 : 28 : g_return_if_fail (source != (gpointer) self);
445 : :
446 : 28 : g_mutex_lock (&self->mutex);
447 : :
448 : 28 : if (source == (gpointer) self->source)
449 : 1 : goto unlock;
450 : :
451 : 27 : if (self->source != NULL)
452 : : {
453 : : guint i;
454 : :
455 : 10 : g_object_weak_unref (self->source,
456 : : g_binding_group__source_weak_notify,
457 : : self);
458 : 10 : self->source = NULL;
459 : :
460 : 35 : for (i = 0; i < self->lazy_bindings->len; i++)
461 : : {
462 : 25 : LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
463 : :
464 : 25 : g_binding_group_disconnect (lazy_binding);
465 : : }
466 : : }
467 : :
468 : 27 : if (source != NULL && g_binding_group_check_source (self, source))
469 : : {
470 : : guint i;
471 : :
472 : 16 : self->source = source;
473 : 16 : g_object_weak_ref (self->source,
474 : : g_binding_group__source_weak_notify,
475 : : self);
476 : :
477 : 48 : for (i = 0; i < self->lazy_bindings->len; i++)
478 : : {
479 : : LazyBinding *lazy_binding;
480 : :
481 : 32 : lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
482 : 32 : g_binding_group_connect (self, lazy_binding);
483 : : }
484 : : }
485 : :
486 : 27 : notify = TRUE;
487 : :
488 : 28 : unlock:
489 : 28 : g_mutex_unlock (&self->mutex);
490 : :
491 : 28 : if (notify)
492 : 27 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SOURCE]);
493 : : }
494 : :
495 : : static void
496 : 20 : g_binding_group_bind_helper (GBindingGroup *self,
497 : : const gchar *source_property,
498 : : gpointer target,
499 : : const gchar *target_property,
500 : : GBindingFlags flags,
501 : : gpointer transform_to,
502 : : gpointer transform_from,
503 : : gpointer user_data,
504 : : GDestroyNotify user_data_destroy,
505 : : gboolean using_closures)
506 : : {
507 : : LazyBinding *lazy_binding;
508 : :
509 : 20 : g_return_if_fail (G_IS_BINDING_GROUP (self));
510 : 20 : g_return_if_fail (source_property != NULL);
511 : 20 : g_return_if_fail (self->source == NULL ||
512 : : g_object_class_find_property (G_OBJECT_GET_CLASS (self->source),
513 : : source_property) != NULL);
514 : 19 : g_return_if_fail (G_IS_OBJECT (target));
515 : 19 : g_return_if_fail (target_property != NULL);
516 : 19 : g_return_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (target),
517 : : target_property) != NULL);
518 : 18 : g_return_if_fail (target != (gpointer) self ||
519 : : strcmp (source_property, target_property) != 0);
520 : :
521 : 18 : g_mutex_lock (&self->mutex);
522 : :
523 : 18 : lazy_binding = g_slice_new0 (LazyBinding);
524 : 18 : lazy_binding->group = self;
525 : 18 : lazy_binding->source_property = g_intern_string (source_property);
526 : 18 : lazy_binding->target_property = g_intern_string (target_property);
527 : 18 : lazy_binding->target = target;
528 : 18 : lazy_binding->binding_flags = flags | G_BINDING_SYNC_CREATE;
529 : 18 : lazy_binding->user_data = user_data;
530 : 18 : lazy_binding->user_data_destroy = user_data_destroy;
531 : 18 : lazy_binding->transform_to = transform_to;
532 : 18 : lazy_binding->transform_from = transform_from;
533 : :
534 : 18 : if (using_closures)
535 : : {
536 : 1 : lazy_binding->using_closures = TRUE;
537 : :
538 : 1 : if (transform_to != NULL)
539 : 1 : g_closure_sink (g_closure_ref (transform_to));
540 : :
541 : 1 : if (transform_from != NULL)
542 : 1 : g_closure_sink (g_closure_ref (transform_from));
543 : : }
544 : :
545 : 18 : g_object_weak_ref (target,
546 : : g_binding_group__target_weak_notify,
547 : : self);
548 : :
549 : 18 : g_ptr_array_add (self->lazy_bindings, lazy_binding);
550 : :
551 : 18 : if (self->source != NULL)
552 : 6 : g_binding_group_connect (self, lazy_binding);
553 : :
554 : 18 : g_mutex_unlock (&self->mutex);
555 : : }
556 : :
557 : : /**
558 : : * g_binding_group_bind:
559 : : * @self: the #GBindingGroup
560 : : * @source_property: the property on the source to bind
561 : : * @target: (type GObject) (transfer none) (not nullable): the target #GObject
562 : : * @target_property: the property on @target to bind
563 : : * @flags: the flags used to create the #GBinding
564 : : *
565 : : * Creates a binding between @source_property on the source object
566 : : * and @target_property on @target. Whenever the @source_property
567 : : * is changed the @target_property is updated using the same value.
568 : : * The binding flag %G_BINDING_SYNC_CREATE is automatically specified.
569 : : *
570 : : * See g_object_bind_property() for more information.
571 : : *
572 : : * Since: 2.72
573 : : */
574 : : void
575 : 17 : g_binding_group_bind (GBindingGroup *self,
576 : : const gchar *source_property,
577 : : gpointer target,
578 : : const gchar *target_property,
579 : : GBindingFlags flags)
580 : : {
581 : 17 : g_binding_group_bind_full (self, source_property,
582 : : target, target_property,
583 : : flags,
584 : : NULL, NULL,
585 : : NULL, NULL);
586 : 17 : }
587 : :
588 : : /**
589 : : * g_binding_group_bind_full:
590 : : * @self: the #GBindingGroup
591 : : * @source_property: the property on the source to bind
592 : : * @target: (type GObject) (transfer none) (not nullable): the target #GObject
593 : : * @target_property: the property on @target to bind
594 : : * @flags: the flags used to create the #GBinding
595 : : * @transform_to: (scope notified) (nullable): the transformation function
596 : : * from the source object to the @target, or %NULL to use the default
597 : : * @transform_from: (scope notified) (nullable): the transformation function
598 : : * from the @target to the source object, or %NULL to use the default
599 : : * @user_data: custom data to be passed to the transformation
600 : : * functions, or %NULL
601 : : * @user_data_destroy: function to be called when disposing the binding,
602 : : * to free the resources used by the transformation functions
603 : : *
604 : : * Creates a binding between @source_property on the source object and
605 : : * @target_property on @target, allowing you to set the transformation
606 : : * functions to be used by the binding. The binding flag
607 : : * %G_BINDING_SYNC_CREATE is automatically specified.
608 : : *
609 : : * See g_object_bind_property_full() for more information.
610 : : *
611 : : * Since: 2.72
612 : : */
613 : : void
614 : 19 : g_binding_group_bind_full (GBindingGroup *self,
615 : : const gchar *source_property,
616 : : gpointer target,
617 : : const gchar *target_property,
618 : : GBindingFlags flags,
619 : : GBindingTransformFunc transform_to,
620 : : GBindingTransformFunc transform_from,
621 : : gpointer user_data,
622 : : GDestroyNotify user_data_destroy)
623 : : {
624 : 19 : g_binding_group_bind_helper (self, source_property,
625 : : target, target_property,
626 : : flags,
627 : : transform_to, transform_from,
628 : : user_data, user_data_destroy,
629 : : FALSE);
630 : 19 : }
631 : :
632 : : /**
633 : : * g_binding_group_bind_with_closures: (rename-to g_binding_group_bind_full)
634 : : * @self: the #GBindingGroup
635 : : * @source_property: the property on the source to bind
636 : : * @target: (type GObject) (transfer none) (not nullable): the target #GObject
637 : : * @target_property: the property on @target to bind
638 : : * @flags: the flags used to create the #GBinding
639 : : * @transform_to: (nullable) (transfer none): a #GClosure wrapping the
640 : : * transformation function from the source object to the @target,
641 : : * or %NULL to use the default
642 : : * @transform_from: (nullable) (transfer none): a #GClosure wrapping the
643 : : * transformation function from the @target to the source object,
644 : : * or %NULL to use the default
645 : : *
646 : : * Creates a binding between @source_property on the source object and
647 : : * @target_property on @target, allowing you to set the transformation
648 : : * functions to be used by the binding. The binding flag
649 : : * %G_BINDING_SYNC_CREATE is automatically specified.
650 : : *
651 : : * This function is the language bindings friendly version of
652 : : * g_binding_group_bind_property_full(), using #GClosures
653 : : * instead of function pointers.
654 : : *
655 : : * See g_object_bind_property_with_closures() for more information.
656 : : *
657 : : * Since: 2.72
658 : : */
659 : : void
660 : 1 : g_binding_group_bind_with_closures (GBindingGroup *self,
661 : : const gchar *source_property,
662 : : gpointer target,
663 : : const gchar *target_property,
664 : : GBindingFlags flags,
665 : : GClosure *transform_to,
666 : : GClosure *transform_from)
667 : : {
668 : 1 : g_binding_group_bind_helper (self, source_property,
669 : : target, target_property,
670 : : flags,
671 : : transform_to, transform_from,
672 : : NULL, NULL,
673 : : TRUE);
674 : 1 : }
|