diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2018-12-19 16:01:17 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2019-03-26 00:11:27 +0000 |
commit | 5cbf6f5fbdf8146a62fa611b2279f587e34ee1f0 (patch) | |
tree | 12eb9ce0997e62210b71a423fc001b2d1d54c1da /gtk/gtklayoutmanager.c | |
parent | 15fda18791ae6df027620a2a8a42899f632337a8 (diff) | |
download | gtk+-5cbf6f5fbdf8146a62fa611b2279f587e34ee1f0.tar.gz |
Add GtkLayoutChild
Layout managers needs a way to store properties that control the layout
policy of a widget; typically, we used to store these in GtkContainer's
child properties, but since GtkLayoutManager is decoupled from the
actual container widget, we need a separate storage. Additionally, child
properties have their own downsides, like requiring a separate, global
GParamSpecPool storage, and additional lookup API.
GtkLayoutChild is a simple GObject class, which means you can introspect
and document it as you would any other type.
Diffstat (limited to 'gtk/gtklayoutmanager.c')
-rw-r--r-- | gtk/gtklayoutmanager.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c index 7a5f2f08d5..02abe0d5c7 100644 --- a/gtk/gtklayoutmanager.c +++ b/gtk/gtklayoutmanager.c @@ -38,6 +38,7 @@ #include "config.h" #include "gtklayoutmanagerprivate.h" +#include "gtklayoutchild.h" #include "gtkwidget.h" #ifdef G_ENABLE_DEBUG @@ -57,6 +58,8 @@ typedef struct { G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkLayoutManager, gtk_layout_manager, G_TYPE_OBJECT) +static GQuark quark_layout_child; + static GtkSizeRequestMode gtk_layout_manager_real_get_request_mode (GtkLayoutManager *manager, GtkWidget *widget) @@ -107,6 +110,8 @@ gtk_layout_manager_class_init (GtkLayoutManagerClass *klass) klass->get_request_mode = gtk_layout_manager_real_get_request_mode; klass->measure = gtk_layout_manager_real_measure; klass->allocate = gtk_layout_manager_real_allocate; + + quark_layout_child = g_quark_from_static_string ("-GtkLayoutManager-layout-child"); } static void @@ -278,3 +283,75 @@ gtk_layout_manager_layout_changed (GtkLayoutManager *manager) if (priv->widget != NULL) gtk_widget_queue_resize (priv->widget); } + +/** + * gtk_layout_manager_get_layout_child: + * @manager: a #GtkLayoutManager + * @widget: a #GtkWidget + * + * Retrieves a #GtkLayoutChild instance for the #GtkLayoutManager, creating + * one if necessary + * + * The #GtkLayoutChild instance is owned by the #GtkLayoutManager, and is + * guaranteed to exist as long as @widget is a child of the #GtkWidget using + * the given #GtkLayoutManager. + * + * Returns: (transfer none): a #GtkLayoutChild + */ +GtkLayoutChild * +gtk_layout_manager_get_layout_child (GtkLayoutManager *manager, + GtkWidget *widget) +{ + GtkLayoutManagerPrivate *priv = gtk_layout_manager_get_instance_private (manager); + GtkLayoutChild *res; + GtkWidget *parent; + + g_return_val_if_fail (GTK_IS_LAYOUT_MANAGER (manager), NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + parent = gtk_widget_get_parent (widget); + g_return_val_if_fail (parent != NULL, NULL); + + if (priv->widget != parent) + { + g_critical ("The parent %s %p of the widget %s %p does not " + "use the given layout manager of type %s %p", + gtk_widget_get_name (parent), parent, + gtk_widget_get_name (widget), widget, + G_OBJECT_TYPE_NAME (manager), manager); + return NULL; + } + + if (GTK_LAYOUT_MANAGER_GET_CLASS (manager)->create_layout_child == NULL) + { + g_critical ("The layout manager of type %s %p does not create " + "GtkLayoutChild instances", + G_OBJECT_TYPE_NAME (manager), manager); + return NULL; + } + + /* We store the LayoutChild into the Widget, so that the LayoutChild + * instance goes away once the Widget goes away + */ + res = g_object_get_qdata (G_OBJECT (widget), quark_layout_child); + if (res != NULL) + { + /* If the LayoutChild instance is stale, and refers to another + * layout manager, then we simply ask the LayoutManager to + * replace it, as it means the layout manager for the parent + * widget was replaced + */ + if (gtk_layout_child_get_layout_manager (res) == manager) + return res; + } + + res = GTK_LAYOUT_MANAGER_GET_CLASS (manager)->create_layout_child (manager, widget); + g_assert (res != NULL); + g_assert (g_type_is_a (G_OBJECT_TYPE (res), GTK_TYPE_LAYOUT_CHILD)); + + g_object_set_qdata_full (G_OBJECT (widget), quark_layout_child, + res, + g_object_unref); + + return res; +} |