From 41ca2069c028df82593e518d176305ded774fd27 Mon Sep 17 00:00:00 2001 From: Denis Washington Date: Sun, 21 Aug 2011 21:51:21 +0200 Subject: [PATCH] Remove support for transformation functions in GtkBuilder property binding code for now The added API would be a burden for language binding authors and requires another call after loading a UI file (like gtk_builder_connect_signals()). This still needs to be fleshed out more. The version with transformation functions were moved to a new "gtkbuilder-gbinding-transform" branch for reference. --- gtk/gtkbuilder.c | 183 +++++++--------------------------------- gtk/gtkbuilder.h | 15 ---- gtk/gtkbuilderparser.c | 6 -- gtk/gtkbuilderprivate.h | 1 - gtk/tests/builder.c | 51 ----------- 5 files changed, 32 insertions(+), 224 deletions(-) diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c index 77eebbbcd9..8fb811398b 100644 --- a/gtk/gtkbuilder.c +++ b/gtk/gtkbuilder.c @@ -93,8 +93,7 @@ * internal-child #IMPLIED > * + * source #REQUIRED> * ]]> * * The toplevel element is <interface>. It optionally takes a "domain" @@ -164,19 +163,13 @@ * another property with a <binding> element. This causes the value * of the property specified with the "to" attribute to be whatever the * property "from" of object "source" is set to, even if that property - * is later set to another value. If present, "transform-func" specifies a - * transformation function that converts the source property value before - * it is passed to the target property. GTK+'s default method for finding - * such a function is using g_module_symbol(); to overridde this behavior, - * a custom #GtkBuilderBindingFunc can be passed to - * gtk_builder_create_bindings_full(). For more information about the - * property binding mechanism, see #GBinding (which GTK+ uses internally). + * is later set to another value. For more information about the property + * binding mechanism, see #GBinding (which GTK+ uses internally). * * Signal handlers are set up with the <signal> element. The "name" * attribute specifies the name of the signal, and the "handler" attribute - * specifies the function to connect to the signal. Like in the case of - * transformation functions, GTK+ tries to find the handler using - * g_module_symbol() by default, but this can be changed by passing + * specifies the function to connect to the signal. By default, GTK+ tries to + * find the handler using g_module_symbol(), but this can be changed by passing * a custom #GtkBuilderConnectFunc to gtk_builder_connect_signals_full(). The * remaining attributes, "after", "swapped" and "object", have the same meaning * as the corresponding parameters of the g_signal_connect_object() or @@ -886,10 +879,37 @@ gtk_builder_apply_delayed_properties (GtkBuilder *builder) g_slist_free (props); } +static void +gtk_builder_create_bindings (GtkBuilder *builder) +{ + GSList *l; + + for (l = builder->priv->bindings; l; l = l->next) + { + BindingInfo *binding = (BindingInfo*)l->data; + GObject *target, *source; + + target = gtk_builder_lookup_object (builder, binding->object_name); + g_assert (target != NULL); + + source = gtk_builder_lookup_object (builder, binding->source); + if (source) + { + g_object_bind_property (source, binding->from, + target, binding->to, + G_BINDING_SYNC_CREATE); + } + } + + g_slist_free (builder->priv->bindings); + builder->priv->bindings = NULL; +} + void _gtk_builder_finish (GtkBuilder *builder) { gtk_builder_apply_delayed_properties (builder); + gtk_builder_create_bindings (builder); } /** @@ -1393,145 +1413,6 @@ gtk_builder_connect_signals_full (GtkBuilder *builder, builder->priv->signals = NULL; } -static void -gtk_builder_create_bindings_default (GtkBuilder *builder, - GObject *source, - const gchar *source_property, - GObject *target, - const gchar *target_property, - const gchar *transform_func, - GBindingFlags flags, - gpointer user_data) -{ - GBindingTransformFunc func = NULL; - connect_args *args = (connect_args*)user_data; - - if (transform_func && - !g_module_symbol (args->module, transform_func, (gpointer)&func)) - { - g_warning ("Could not find binding transformation function '%s'", - transform_func); - return; - } - - g_object_bind_property_full (source, source_property, - target, target_property, - flags | G_BINDING_SYNC_CREATE, - func, NULL, - args->data, NULL); -} - -/** - * gtk_builder_create_bindings: - * @builder: a #GtkBuilder - * @user_data: a pointer to a structure sent in as user data to all signals - * - * This function establishes all property bindings defined in the interface - * description. It uses g_object_bind_property_full() with the - * #G_BINDING_SYNC_CREATE flag flag for this purpose. Like - * gtk_builder_connect_signals(), #GModule is used to match any - * transformation function names given in the interface description with - * symbols exported through the application's symbol table. To overide - * this behavior with a different binding creation method, use - * gtk_builder_create_bindings_full() with a custom #GtkBuilderBindingFunc - * instead. - * - * Note that this function requires #GModule to be supported on the platform - * to work. It can only be called once, subsequent calls will do nothing. - * - * When compiling applications for Windows, you must declare transformation - * functions with #G_MODULE_EXPORT, or they will not be put in the symbol - * table. On Linux and Unices, this is not necessary; applications should - * instead be compiled with the -Wl,--export-dynamic CFLAGS, and linked - * against gmodule-export-2.0. - */ -void -gtk_builder_create_bindings (GtkBuilder *builder, - gpointer user_data) -{ - /* Reuse connect_args from gtk_builder_connect_signals */ - connect_args *args; - - g_return_if_fail (GTK_IS_BUILDER (builder)); - - if (!g_module_supported ()) - g_error ("gtk_builder_create_bindings() requires working GModule"); - - args = g_slice_new0 (connect_args); - args->module = g_module_open (NULL, G_MODULE_BIND_LAZY); - args->data = user_data; - - gtk_builder_create_bindings_full (builder, - gtk_builder_create_bindings_default, - args); - g_module_close (args->module); - - g_slice_free (connect_args, args); -} - -/** - * GtkBuilderBindingFunc: - * @builder: a #GtkBuilder - * @source: the binding source object - * @source_property: the binding source property - * @target: the binding target object - * @target_property: the binding target property - * @flags: #GBindingFlags to use - * @user_data: user data - * - * The signature of a function used to create property bindings, used by the - * gtk_builder_create_bindings() and gtk_builder_create_bindings_full() - * methods. Like #GtkBuilderConnectFunc, its main use case is bindings for - * interpreted programming languages. - * - * Since: ? - */ - -/** - * gtk_builder_create_bindings_full: - * @builder: a #GtkBuilder - * @func: (scope call): the function used to create the bindings - * @user_data: arbitrary data that will be passed to the binding function - * - * Calls @func for every property binding defined in the interface description - * in order to create it. Like gtk_builder_connect_signals_full(), this - * function is mainly thought as a version of gtk_builder_create_bindings() - * suitable for interpreted language bindings, but has other uses too. - */ -void -gtk_builder_create_bindings_full (GtkBuilder *builder, - GtkBuilderBindingFunc func, - gpointer user_data) -{ - GSList *l; - - builder->priv->bindings = g_slist_reverse (builder->priv->bindings); - for (l = builder->priv->bindings; l; l = l->next) - { - BindingInfo *binding = (BindingInfo*)l->data; - GObject *target, *source; - - target = gtk_builder_lookup_object (builder, binding->object_name); - g_assert (target != NULL); - - source = gtk_builder_lookup_object (builder, binding->source); - if (!source) - { - g_warning ("Could not lookup source object %s for binding to " - "property %s of object %s", - binding->source, binding->to, binding->object_name); - continue; - } - - func (builder, source, binding->from, target, binding->to, - binding->transform_func, 0, user_data); - } - - g_slist_foreach (builder->priv->bindings, (GFunc)_free_binding_info, NULL); - g_slist_free (builder->priv->bindings); - builder->priv->bindings = NULL; -} - /** * gtk_builder_value_from_string: * @builder: a #GtkBuilder diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h index a39cbc6709..cdbd06f673 100644 --- a/gtk/gtkbuilder.h +++ b/gtk/gtkbuilder.h @@ -113,15 +113,6 @@ typedef void (*GtkBuilderConnectFunc) (GtkBuilder *builder, GConnectFlags flags, gpointer user_data); -typedef void (*GtkBuilderBindingFunc) (GtkBuilder *builder, - GObject *source, - const gchar *source_property, - GObject *target, - const gchar *target_property, - const gchar *transform_func, - GBindingFlags flags, - gpointer user_data); - GType gtk_builder_get_type (void) G_GNUC_CONST; GtkBuilder* gtk_builder_new (void); @@ -149,12 +140,6 @@ void gtk_builder_connect_signals (GtkBuilder *builder, void gtk_builder_connect_signals_full (GtkBuilder *builder, GtkBuilderConnectFunc func, gpointer user_data); -void gtk_builder_create_bindings (GtkBuilder *builder, - gpointer user_data); -void gtk_builder_create_bindings_full (GtkBuilder *builder, - GtkBuilderBindingFunc func, - gpointer user_data); - void gtk_builder_set_translation_domain (GtkBuilder *builder, const gchar *domain); const gchar* gtk_builder_get_translation_domain (GtkBuilder *builder); diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c index 80178186b9..f81d180c26 100644 --- a/gtk/gtkbuilderparser.c +++ b/gtk/gtkbuilderparser.c @@ -544,7 +544,6 @@ parse_binding (ParserData *data, const gchar *to = NULL; const gchar *from = NULL; const gchar *source = NULL; - const gchar *transform_func = NULL; ObjectInfo *object_info; int i; @@ -563,8 +562,6 @@ parse_binding (ParserData *data, from = values[i]; else if (strcmp (names[i], "source") == 0) source = values[i]; - else if (strcmp (names[i], "transform-func") == 0) - transform_func = values[i]; else { error_invalid_attribute (data, element_name, names[i], error); @@ -592,8 +589,6 @@ parse_binding (ParserData *data, info->to = g_strdup (to); info->from = g_strdup (from); info->source = g_strdup (source); - if (transform_func) - info->transform_func = g_strdup (transform_func); state_push (data, info); info->tag.name = element_name; @@ -708,7 +703,6 @@ _free_binding_info (BindingInfo *info, g_free (info->to); g_free (info->from); g_free (info->source); - g_free (info->transform_func); g_slice_free (BindingInfo, info); } diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h index 931b8119d0..52a6010420 100644 --- a/gtk/gtkbuilderprivate.h +++ b/gtk/gtkbuilderprivate.h @@ -68,7 +68,6 @@ typedef struct { gchar *to; gchar *from; gchar *source; - gchar *transform_func; } BindingInfo; typedef struct { diff --git a/gtk/tests/builder.c b/gtk/tests/builder.c index 80bc9176bb..9dd30830a6 100644 --- a/gtk/tests/builder.c +++ b/gtk/tests/builder.c @@ -2601,7 +2601,6 @@ test_property_bindings (void) GObject *checkbutton, *button, *window; builder = builder_new_from_string (buffer, -1, NULL); - gtk_builder_create_bindings (builder, NULL); checkbutton = gtk_builder_get_object (builder, "checkbutton"); g_assert (checkbutton != NULL); @@ -2639,55 +2638,6 @@ reverse_func (GBinding *binding, return TRUE; } -static void -test_transform_funcs (void) -{ - const gchar *buffer = - "" - " " - " " - " " - " True" - " vertical" - " " - " " - " GTK+" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - - GtkBuilder *builder; - GObject *entry, *button, *window; - - builder = builder_new_from_string (buffer, -1, NULL); - gtk_builder_create_bindings (builder, "user_data"); - - entry = gtk_builder_get_object (builder, "entry"); - g_assert (entry != NULL); - g_assert (GTK_IS_ENTRY (entry)); - g_assert (strcmp (gtk_entry_get_text (GTK_ENTRY (entry)), "GTK+") == 0); - - button = gtk_builder_get_object (builder, "button"); - g_assert (button != NULL); - g_assert (GTK_IS_BUTTON (button)); - g_assert (strcmp (gtk_button_get_label (GTK_BUTTON (button)), "+KTG") == 0); - - gtk_entry_set_text (GTK_ENTRY (entry), "rocks"); - g_assert (strcmp (gtk_button_get_label (GTK_BUTTON (button)), "skcor") == 0); - - window = gtk_builder_get_object (builder, "window"); - gtk_widget_destroy (GTK_WIDGET (window)); - g_object_unref (builder); -} - int main (int argc, char **argv) { @@ -2735,7 +2685,6 @@ main (int argc, char **argv) g_test_add_func ("/Builder/MessageArea", test_message_area); g_test_add_func ("/Builder/MessageDialog", test_message_dialog); g_test_add_func ("/Builder/Property Bindings", test_property_bindings); - g_test_add_func ("/Builder/Transformation Functions", test_transform_funcs); return g_test_run(); }