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 [ + + + - : 161 : 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 : 2 : g_binding_group_class_init (GBindingGroupClass *klass)
332 : : {
333 : 2 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
334 : :
335 : 2 : object_class->dispose = g_binding_group_dispose;
336 : 2 : object_class->finalize = g_binding_group_finalize;
337 : 2 : object_class->get_property = g_binding_group_get_property;
338 : 2 : 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 : 2 : properties[PROP_SOURCE] =
348 : 2 : g_param_spec_object ("source",
349 : : "Source",
350 : : "The source GObject used for binding properties.",
351 : : G_TYPE_OBJECT,
352 : : (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
353 : :
354 : 2 : g_object_class_install_properties (object_class, N_PROPS, properties);
355 : 2 : }
356 : :
357 : : static void
358 : 12 : g_binding_group_init (GBindingGroup *self)
359 : : {
360 : 12 : g_mutex_init (&self->mutex);
361 : 12 : self->lazy_bindings = g_ptr_array_new_with_free_func (lazy_binding_free);
362 : 12 : }
363 : :
364 : : /**
365 : : * g_binding_group_new:
366 : : *
367 : : * Creates a new #GBindingGroup.
368 : : *
369 : : * Returns: (transfer full): a new #GBindingGroup
370 : : *
371 : : * Since: 2.72
372 : : */
373 : : GBindingGroup *
374 : 11 : g_binding_group_new (void)
375 : : {
376 : 11 : return g_object_new (G_TYPE_BINDING_GROUP, NULL);
377 : : }
378 : :
379 : : /**
380 : : * g_binding_group_dup_source:
381 : : * @self: the #GBindingGroup
382 : : *
383 : : * Gets the source object used for binding properties.
384 : : *
385 : : * Returns: (transfer none) (nullable) (type GObject): a #GObject or %NULL.
386 : : *
387 : : * Since: 2.72
388 : : */
389 : : gpointer
390 : 17 : g_binding_group_dup_source (GBindingGroup *self)
391 : : {
392 : : GObject *source;
393 : :
394 : 17 : g_return_val_if_fail (G_IS_BINDING_GROUP (self), NULL);
395 : :
396 : 17 : g_mutex_lock (&self->mutex);
397 [ + + ]: 17 : source = self->source ? g_object_ref (self->source) : NULL;
398 : 17 : g_mutex_unlock (&self->mutex);
399 : :
400 : 17 : return source;
401 : : }
402 : :
403 : : static gboolean
404 : 17 : g_binding_group_check_source (GBindingGroup *self,
405 : : gpointer source)
406 : : {
407 : : guint i;
408 : :
409 : 17 : g_assert (G_IS_BINDING_GROUP (self));
410 : 17 : g_assert (!source || G_IS_OBJECT (source));
411 : :
412 [ + + ]: 49 : for (i = 0; i < self->lazy_bindings->len; i++)
413 : : {
414 : 33 : LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
415 : :
416 : 33 : g_return_val_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
417 : : lazy_binding->source_property) != NULL,
418 : : FALSE);
419 : : }
420 : :
421 : 16 : return TRUE;
422 : : }
423 : :
424 : : /**
425 : : * g_binding_group_set_source:
426 : : * @self: the #GBindingGroup
427 : : * @source: (type GObject) (nullable) (transfer none): the source #GObject,
428 : : * or %NULL to clear it
429 : : *
430 : : * Sets @source as the source object used for creating property
431 : : * bindings. If there is already a source object all bindings from it
432 : : * will be removed.
433 : : *
434 : : * Note that all properties that have been bound must exist on @source.
435 : : *
436 : : * Since: 2.72
437 : : */
438 : : void
439 : 28 : g_binding_group_set_source (GBindingGroup *self,
440 : : gpointer source)
441 : : {
442 : 28 : gboolean notify = FALSE;
443 : :
444 : 28 : g_return_if_fail (G_IS_BINDING_GROUP (self));
445 : 28 : g_return_if_fail (!source || G_IS_OBJECT (source));
446 : 28 : g_return_if_fail (source != (gpointer) self);
447 : :
448 : 28 : g_mutex_lock (&self->mutex);
449 : :
450 [ + + ]: 28 : if (source == (gpointer) self->source)
451 : 1 : goto unlock;
452 : :
453 [ + + ]: 27 : if (self->source != NULL)
454 : : {
455 : : guint i;
456 : :
457 : 10 : g_object_weak_unref (self->source,
458 : : g_binding_group__source_weak_notify,
459 : : self);
460 : 10 : self->source = NULL;
461 : :
462 [ + + ]: 35 : for (i = 0; i < self->lazy_bindings->len; i++)
463 : : {
464 : 25 : LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
465 : :
466 : 25 : g_binding_group_disconnect (lazy_binding);
467 : : }
468 : : }
469 : :
470 [ + + + + ]: 27 : if (source != NULL && g_binding_group_check_source (self, source))
471 : : {
472 : : guint i;
473 : :
474 : 16 : self->source = source;
475 : 16 : g_object_weak_ref (self->source,
476 : : g_binding_group__source_weak_notify,
477 : : self);
478 : :
479 [ + + ]: 48 : for (i = 0; i < self->lazy_bindings->len; i++)
480 : : {
481 : : LazyBinding *lazy_binding;
482 : :
483 : 32 : lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
484 : 32 : g_binding_group_connect (self, lazy_binding);
485 : : }
486 : : }
487 : :
488 : 27 : notify = TRUE;
489 : :
490 : 28 : unlock:
491 : 28 : g_mutex_unlock (&self->mutex);
492 : :
493 [ + + ]: 28 : if (notify)
494 : 27 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SOURCE]);
495 : : }
496 : :
497 : : static void
498 : 20 : g_binding_group_bind_helper (GBindingGroup *self,
499 : : const gchar *source_property,
500 : : gpointer target,
501 : : const gchar *target_property,
502 : : GBindingFlags flags,
503 : : gpointer transform_to,
504 : : gpointer transform_from,
505 : : gpointer user_data,
506 : : GDestroyNotify user_data_destroy,
507 : : gboolean using_closures)
508 : : {
509 : : LazyBinding *lazy_binding;
510 : :
511 : 20 : g_return_if_fail (G_IS_BINDING_GROUP (self));
512 : 20 : g_return_if_fail (source_property != NULL);
513 : 20 : g_return_if_fail (self->source == NULL ||
514 : : g_object_class_find_property (G_OBJECT_GET_CLASS (self->source),
515 : : source_property) != NULL);
516 : 19 : g_return_if_fail (G_IS_OBJECT (target));
517 : 19 : g_return_if_fail (target_property != NULL);
518 : 19 : g_return_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (target),
519 : : target_property) != NULL);
520 : 18 : g_return_if_fail (target != (gpointer) self ||
521 : : strcmp (source_property, target_property) != 0);
522 : :
523 : 18 : g_mutex_lock (&self->mutex);
524 : :
525 : 18 : lazy_binding = g_slice_new0 (LazyBinding);
526 : 18 : lazy_binding->group = self;
527 : 18 : lazy_binding->source_property = g_intern_string (source_property);
528 : 18 : lazy_binding->target_property = g_intern_string (target_property);
529 : 18 : lazy_binding->target = target;
530 : 18 : lazy_binding->binding_flags = flags | G_BINDING_SYNC_CREATE;
531 : 18 : lazy_binding->user_data = user_data;
532 : 18 : lazy_binding->user_data_destroy = user_data_destroy;
533 : 18 : lazy_binding->transform_to = transform_to;
534 : 18 : lazy_binding->transform_from = transform_from;
535 : :
536 [ + + ]: 18 : if (using_closures)
537 : : {
538 : 1 : lazy_binding->using_closures = TRUE;
539 : :
540 [ + - ]: 1 : if (transform_to != NULL)
541 : 1 : g_closure_sink (g_closure_ref (transform_to));
542 : :
543 [ + - ]: 1 : if (transform_from != NULL)
544 : 1 : g_closure_sink (g_closure_ref (transform_from));
545 : : }
546 : :
547 : 18 : g_object_weak_ref (target,
548 : : g_binding_group__target_weak_notify,
549 : : self);
550 : :
551 : 18 : g_ptr_array_add (self->lazy_bindings, lazy_binding);
552 : :
553 [ + + ]: 18 : if (self->source != NULL)
554 : 6 : g_binding_group_connect (self, lazy_binding);
555 : :
556 : 18 : g_mutex_unlock (&self->mutex);
557 : : }
558 : :
559 : : /**
560 : : * g_binding_group_bind:
561 : : * @self: the #GBindingGroup
562 : : * @source_property: the property on the source to bind
563 : : * @target: (type GObject) (transfer none) (not nullable): the target #GObject
564 : : * @target_property: the property on @target to bind
565 : : * @flags: the flags used to create the #GBinding
566 : : *
567 : : * Creates a binding between @source_property on the source object
568 : : * and @target_property on @target. Whenever the @source_property
569 : : * is changed the @target_property is updated using the same value.
570 : : * The binding flag %G_BINDING_SYNC_CREATE is automatically specified.
571 : : *
572 : : * See g_object_bind_property() for more information.
573 : : *
574 : : * Since: 2.72
575 : : */
576 : : void
577 : 17 : g_binding_group_bind (GBindingGroup *self,
578 : : const gchar *source_property,
579 : : gpointer target,
580 : : const gchar *target_property,
581 : : GBindingFlags flags)
582 : : {
583 : 17 : g_binding_group_bind_full (self, source_property,
584 : : target, target_property,
585 : : flags,
586 : : NULL, NULL,
587 : : NULL, NULL);
588 : 17 : }
589 : :
590 : : /**
591 : : * g_binding_group_bind_full:
592 : : * @self: the #GBindingGroup
593 : : * @source_property: the property on the source to bind
594 : : * @target: (type GObject) (transfer none) (not nullable): the target #GObject
595 : : * @target_property: the property on @target to bind
596 : : * @flags: the flags used to create the #GBinding
597 : : * @transform_to: (scope notified) (nullable): the transformation function
598 : : * from the source object to the @target, or %NULL to use the default
599 : : * @transform_from: (scope notified) (nullable): the transformation function
600 : : * from the @target to the source object, or %NULL to use the default
601 : : * @user_data: custom data to be passed to the transformation
602 : : * functions, or %NULL
603 : : * @user_data_destroy: function to be called when disposing the binding,
604 : : * to free the resources used by the transformation functions
605 : : *
606 : : * Creates a binding between @source_property on the source object and
607 : : * @target_property on @target, allowing you to set the transformation
608 : : * functions to be used by the binding. The binding flag
609 : : * %G_BINDING_SYNC_CREATE is automatically specified.
610 : : *
611 : : * See g_object_bind_property_full() for more information.
612 : : *
613 : : * Since: 2.72
614 : : */
615 : : void
616 : 19 : g_binding_group_bind_full (GBindingGroup *self,
617 : : const gchar *source_property,
618 : : gpointer target,
619 : : const gchar *target_property,
620 : : GBindingFlags flags,
621 : : GBindingTransformFunc transform_to,
622 : : GBindingTransformFunc transform_from,
623 : : gpointer user_data,
624 : : GDestroyNotify user_data_destroy)
625 : : {
626 : 19 : g_binding_group_bind_helper (self, source_property,
627 : : target, target_property,
628 : : flags,
629 : : transform_to, transform_from,
630 : : user_data, user_data_destroy,
631 : : FALSE);
632 : 19 : }
633 : :
634 : : /**
635 : : * g_binding_group_bind_with_closures: (rename-to g_binding_group_bind_full)
636 : : * @self: the #GBindingGroup
637 : : * @source_property: the property on the source to bind
638 : : * @target: (type GObject) (transfer none) (not nullable): the target #GObject
639 : : * @target_property: the property on @target to bind
640 : : * @flags: the flags used to create the #GBinding
641 : : * @transform_to: (nullable) (transfer none): a #GClosure wrapping the
642 : : * transformation function from the source object to the @target,
643 : : * or %NULL to use the default
644 : : * @transform_from: (nullable) (transfer none): a #GClosure wrapping the
645 : : * transformation function from the @target to the source object,
646 : : * or %NULL to use the default
647 : : *
648 : : * Creates a binding between @source_property on the source object and
649 : : * @target_property on @target, allowing you to set the transformation
650 : : * functions to be used by the binding. The binding flag
651 : : * %G_BINDING_SYNC_CREATE is automatically specified.
652 : : *
653 : : * This function is the language bindings friendly version of
654 : : * g_binding_group_bind_property_full(), using #GClosures
655 : : * instead of function pointers.
656 : : *
657 : : * See g_object_bind_property_with_closures() for more information.
658 : : *
659 : : * Since: 2.72
660 : : */
661 : : void
662 : 1 : g_binding_group_bind_with_closures (GBindingGroup *self,
663 : : const gchar *source_property,
664 : : gpointer target,
665 : : const gchar *target_property,
666 : : GBindingFlags flags,
667 : : GClosure *transform_to,
668 : : GClosure *transform_from)
669 : : {
670 : 1 : g_binding_group_bind_helper (self, source_property,
671 : : target, target_property,
672 : : flags,
673 : : transform_to, transform_from,
674 : : NULL, NULL,
675 : : TRUE);
676 : 1 : }
|