summaryrefslogtreecommitdiff
path: root/gtk/gtklayoutmanager.c
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2018-12-19 16:01:17 +0000
committerEmmanuele Bassi <ebassi@gnome.org>2019-03-26 00:11:27 +0000
commit5cbf6f5fbdf8146a62fa611b2279f587e34ee1f0 (patch)
tree12eb9ce0997e62210b71a423fc001b2d1d54c1da /gtk/gtklayoutmanager.c
parent15fda18791ae6df027620a2a8a42899f632337a8 (diff)
downloadgtk+-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.c77
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;
+}