From ca2ebaf90f0f49b89118a9db644a493fd56a2d28 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 23 Nov 2019 05:21:17 +0100 Subject: [PATCH] expression: Make property expression allow subexpressions --- gtk/gtkexpression.c | 68 +++++++++++++++++++++++++++++++++++++++------ gtk/gtkexpression.h | 1 + 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/gtk/gtkexpression.c b/gtk/gtkexpression.c index 4ec4e0066a..a4e8a725e1 100644 --- a/gtk/gtkexpression.c +++ b/gtk/gtkexpression.c @@ -295,12 +295,53 @@ struct _GtkPropertyExpression { GtkExpression parent; + GtkExpression *expr; + GParamSpec *pspec; }; static void gtk_property_expression_finalize (GtkExpression *expr) { + GtkPropertyExpression *self = (GtkPropertyExpression *) expr; + + g_clear_pointer (&self->expr, gtk_expression_unref); +} + +static GObject * +gtk_property_expression_get_object (GtkPropertyExpression *self, + gpointer this) +{ + GValue expr_value = G_VALUE_INIT; + GObject *object; + + if (self->expr == NULL) + { + if (this) + return g_object_ref (this); + else + return NULL; + } + + if (!gtk_expression_evaluate (self->expr, this, &expr_value)) + return NULL; + + if (!G_VALUE_HOLDS_OBJECT (&expr_value)) + { + g_value_unset (&expr_value); + return NULL; + } + + object = g_value_dup_object (&expr_value); + g_value_unset (&expr_value); + + if (!G_TYPE_CHECK_INSTANCE_TYPE (object, self->pspec->owner_type)) + { + g_object_unref (object); + return NULL; + } + + return object; } static gboolean @@ -309,11 +350,14 @@ gtk_property_expression_evaluate (GtkExpression *expr, GValue *value) { GtkPropertyExpression *self = (GtkPropertyExpression *) expr; + GObject *object; - if (!G_TYPE_CHECK_INSTANCE_TYPE (this, self->pspec->owner_type)) + object = gtk_property_expression_get_object (self, this); + if (object == NULL) return FALSE; - g_object_get_property (this, self->pspec->name, value); + g_object_get_property (object, self->pspec->name, value); + g_object_unref (object); return TRUE; } @@ -328,20 +372,27 @@ static const GtkExpressionClass GTK_PROPERTY_EXPRESSION_CLASS = /** * gtk_property_expression_new: * @this_type: The type to expect for the this type + * @expression: (nullable) (transfer full): Expression to + * evaluate to get the object to query or %NULL to + * query the `this` object * @property_name: name of the property * - * Creates an expression that looks up a property on the - * passed in object when it is evaluated. - * If gtk_expresson_evaluate() is called with an object of - * another type, this expression's evaluation will fail. + * Creates an expression that looks up a property via the + * given @expression or the `this` argument when @expression + * is %NULL. + * + * If the resulting object conforms to @this_type, its property + * named @property_name will be queried. + * Otherwise, this expression's evaluation will fail. * * The given @this_type must have a property with @property_name. * * Returns: a new #GtkExpression **/ GtkExpression * -gtk_property_expression_new (GType this_type, - const char *property_name) +gtk_property_expression_new (GType this_type, + GtkExpression *expression, + const char *property_name) { GtkPropertyExpression *result; GParamSpec *pspec; @@ -369,6 +420,7 @@ gtk_property_expression_new (GType this_type, result = gtk_expression_alloc (>K_PROPERTY_EXPRESSION_CLASS, pspec->value_type); result->pspec = pspec; + result->expr = expression; return (GtkExpression *) result; } diff --git a/gtk/gtkexpression.h b/gtk/gtkexpression.h index 22d2f9fc22..ebcc586b1f 100644 --- a/gtk/gtkexpression.h +++ b/gtk/gtkexpression.h @@ -48,6 +48,7 @@ gboolean gtk_expression_evaluate (GtkExpression GDK_AVAILABLE_IN_ALL GtkExpression * gtk_property_expression_new (GType this_type, + GtkExpression *expression, const char *property_name); GDK_AVAILABLE_IN_ALL GtkExpression * gtk_constant_expression_new (GType value_type,