From f587cb57f249a8f4b869231ca20f5f19602a20ec Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 21 Jun 2010 12:26:42 +0100 Subject: [PATCH] binding: Add SYNC_CREATE to the flags When creating a binding between two object properties we might want to automatically synchronize the two values at the moment of the binding creation, instead of waiting for the next change. The G_BINDING_SYNC_CREATE flag does exactly what it says on the tin. https://bugzilla.gnome.org/show_bug.cgi?id=622281 --- gobject/gbinding.c | 9 +++++++++ gobject/gbinding.h | 6 +++++- gobject/tests/binding.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/gobject/gbinding.c b/gobject/gbinding.c index 628ede9..8bb91a8 100644 --- a/gobject/gbinding.c +++ b/gobject/gbinding.c @@ -124,6 +124,7 @@ g_binding_flags_get_type (void) static const GFlagsValue values[] = { { G_BINDING_DEFAULT, "G_BINDING_DEFAULT", "default" }, { G_BINDING_BIDIRECTIONAL, "G_BINDING_BIDIRECTIONAL", "bidirectional" }, + { G_BINDING_SYNC_CREATE, "G_BINDING_SYNC_CREATE", "sync-create" }, { 0, NULL, NULL } }; GType g_define_type_id = @@ -893,6 +894,14 @@ g_object_bind_property_full (gpointer source, binding->transform_data = user_data; binding->notify = notify; + /* synchronize the target with the source by faking an emission of + * the ::notify signal for the source property; this will also take + * care of the bidirectional binding case because the eventual change + * will emit a notification on the target + */ + if (flags & G_BINDING_SYNC_CREATE) + on_source_notify (binding->source, binding->source_pspec, binding); + return binding; } diff --git a/gobject/gbinding.h b/gobject/gbinding.h index 90dac60..6a5cc0f 100644 --- a/gobject/gbinding.h +++ b/gobject/gbinding.h @@ -76,6 +76,9 @@ typedef gboolean (* GBindingTransformFunc) (GBinding *binding, * @G_BINDING_BIDIRECTIONAL: Bidirectional binding; if either the * property of the source or the property of the target changes, * the other is updated + * @G_BINDING_SYNC_CREATE: Synchronize the values of the source and + * target properties when creating the binding; the direction of + * the synchronization is always from the source to the target * * Flags to be passed to g_object_bind_property() or * g_object_bind_property_full(). @@ -87,7 +90,8 @@ typedef gboolean (* GBindingTransformFunc) (GBinding *binding, typedef enum { /*< prefix=G_BINDING >*/ G_BINDING_DEFAULT = 0, - G_BINDING_BIDIRECTIONAL = 1 << 0 + G_BINDING_BIDIRECTIONAL = 1 << 0, + G_BINDING_SYNC_CREATE = 1 << 1 } GBindingFlags; GType g_binding_flags_get_type (void) G_GNUC_CONST; diff --git a/gobject/tests/binding.c b/gobject/tests/binding.c index eef4590..c4d4ffe 100644 --- a/gobject/tests/binding.c +++ b/gobject/tests/binding.c @@ -346,6 +346,41 @@ binding_chain (void) g_object_unref (c); } +static void +binding_sync_create (void) +{ + BindingSource *source = g_object_new (binding_source_get_type (), + "foo", 42, + NULL); + BindingTarget *target = g_object_new (binding_target_get_type (), + "bar", 47, + NULL); + GBinding *binding; + + binding = g_object_bind_property (source, "foo", + target, "bar", + G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); + + g_assert_cmpint (source->foo, ==, 42); + g_assert_cmpint (target->bar, ==, 42); + + g_object_set (source, "foo", 47, NULL); + g_assert_cmpint (source->foo, ==, target->bar); + + g_object_unref (binding); + + g_object_set (target, "bar", 49, NULL); + + binding = g_object_bind_property (source, "foo", + target, "bar", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_assert_cmpint (source->foo, ==, 47); + g_assert_cmpint (target->bar, ==, 47); + + g_object_unref (source); + g_object_unref (target); +} + int main (int argc, char *argv[]) { @@ -356,6 +391,7 @@ main (int argc, char *argv[]) g_test_add_func ("/binding/bidirectional", binding_bidirectional); g_test_add_func ("/binding/transform", binding_transform); g_test_add_func ("/binding/chain", binding_chain); + g_test_add_func ("/binding/sync-create", binding_sync_create); return g_test_run (); } -- 2.7.4