[gtk/wip/layout-manager: 40/43] wip: Hook GtkLayoutManager into GtkWidget
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/layout-manager: 40/43] wip: Hook GtkLayoutManager into GtkWidget
- Date: Wed, 19 Dec 2018 16:06:07 +0000 (UTC)
commit 9dd03fbcd7537b4983ad59b2b75a525d2b4b7023
Author: Emmanuele Bassi <ebassi gnome org>
Date: Wed Dec 12 17:20:28 2018 +0000
wip: Hook GtkLayoutManager into GtkWidget
We delegate the size request mode, the measuring, and the allocation of
a widget through a GtkLayoutManager instance, if one has been attached
to the widget—otherwise we fall back to the widget's own implementation.
gtk/gtklayoutmanager.c | 3 +-
gtk/gtklayoutmanager.h | 3 +-
gtk/gtksizerequest.c | 121 ++++++++++++++++++++++++++++++++++---------------
gtk/gtktypes.h | 1 +
gtk/gtkwidget.c | 76 +++++++++++++++++++++++++++----
gtk/gtkwidget.h | 6 +++
gtk/gtkwidgetprivate.h | 3 ++
7 files changed, 166 insertions(+), 47 deletions(-)
---
diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c
index bb23c5a598..fce5b863c1 100644
--- a/gtk/gtklayoutmanager.c
+++ b/gtk/gtklayoutmanager.c
@@ -27,7 +27,8 @@
#include "config.h"
-#include "gtklayoutmanager.h"
+#include "gtklayoutmanagerprivate.h"
+#include "gtkwidget.h"
#ifdef G_ENABLE_DEBUG
#define LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED(m,method) G_STMT_START { \
diff --git a/gtk/gtklayoutmanager.h b/gtk/gtklayoutmanager.h
index e849e300a2..20987212b8 100644
--- a/gtk/gtklayoutmanager.h
+++ b/gtk/gtklayoutmanager.h
@@ -18,7 +18,8 @@
*/
#pragma once
-#include <gtk/gtkcontainer.h>
+#include <gtk/gtktypes.h>
+#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index 197d2413ea..cd25debcae 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -31,6 +31,7 @@
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcssnumbervalueprivate.h"
+#include "gtklayoutmanagerprivate.h"
#ifdef G_ENABLE_CONSISTENCY_CHECKS
@@ -195,45 +196,87 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
css_min_for_size = get_number_ceil (style, GTK_CSS_PROPERTY_MIN_WIDTH);
}
- if (for_size < 0)
+ GtkLayoutManager *layout_manager = gtk_widget_get_layout_manager (widget);
+
+ if (layout_manager != NULL)
{
- push_recursion_check (widget, orientation);
- widget_class->measure (widget, orientation, -1,
- &reported_min_size, &reported_nat_size,
- &min_baseline, &nat_baseline);
- pop_recursion_check (widget, orientation);
+ if (for_size < 0)
+ {
+ gtk_layout_manager_measure (layout_manager, widget,
+ orientation, -1,
+ &reported_min_size, &reported_nat_size,
+ &min_baseline, &nat_baseline);
+ }
+ else
+ {
+ int adjusted_for_size;
+ int minimum_for_size = 0;
+ int natural_for_size = 0;
+ int dummy = 0;
+
+ /* Pull the minimum for_size from the cache as it's needed to adjust
+ * the proposed 'for_size' */
+ gtk_layout_manager_measure (layout_manager, widget,
+ OPPOSITE_ORIENTATION (orientation), -1,
+ &minimum_for_size, &natural_for_size,
+ NULL, NULL);
+
+ if (for_size < MAX (minimum_for_size, css_min_for_size))
+ for_size = MAX (minimum_for_size, css_min_for_size);
+
+ adjusted_for_size = for_size;
+ gtk_widget_adjust_size_allocation (widget, OPPOSITE_ORIENTATION (orientation),
+ &for_size, &natural_for_size,
+ &dummy, &adjusted_for_size);
+ adjusted_for_size -= css_extra_for_size;
+
+ gtk_layout_manager_measure (layout_manager, widget,
+ orientation, adjusted_for_size,
+ &reported_min_size, &reported_nat_size,
+ &min_baseline, &nat_baseline);
+ }
}
else
{
- int adjusted_for_size;
- int minimum_for_size = 0;
- int natural_for_size = 0;
- int dummy = 0;
-
- /* Pull the minimum for_size from the cache as it's needed to adjust
- * the proposed 'for_size' */
- gtk_widget_measure (widget, OPPOSITE_ORIENTATION (orientation), -1,
- &minimum_for_size, &natural_for_size, NULL, NULL);
-
- /* TODO: Warn if the given for_size is too small? */
- if (for_size < MAX (minimum_for_size, css_min_for_size))
- for_size = MAX (minimum_for_size, css_min_for_size);
-
- adjusted_for_size = for_size;
- gtk_widget_adjust_size_allocation (widget, OPPOSITE_ORIENTATION (orientation),
- &for_size, &natural_for_size,
- &dummy, &adjusted_for_size);
-
- adjusted_for_size -= css_extra_for_size;
-
- push_recursion_check (widget, orientation);
- widget_class->measure (widget,
- orientation,
- adjusted_for_size,
- &reported_min_size, &reported_nat_size,
- &min_baseline, &nat_baseline);
- pop_recursion_check (widget, orientation);
-
+ if (for_size < 0)
+ {
+ push_recursion_check (widget, orientation);
+ widget_class->measure (widget, orientation, -1,
+ &reported_min_size, &reported_nat_size,
+ &min_baseline, &nat_baseline);
+ pop_recursion_check (widget, orientation);
+ }
+ else
+ {
+ int adjusted_for_size;
+ int minimum_for_size = 0;
+ int natural_for_size = 0;
+ int dummy = 0;
+
+ /* Pull the minimum for_size from the cache as it's needed to adjust
+ * the proposed 'for_size' */
+ gtk_widget_measure (widget, OPPOSITE_ORIENTATION (orientation), -1,
+ &minimum_for_size, &natural_for_size, NULL, NULL);
+
+ /* TODO: Warn if the given for_size is too small? */
+ if (for_size < MAX (minimum_for_size, css_min_for_size))
+ for_size = MAX (minimum_for_size, css_min_for_size);
+
+ adjusted_for_size = for_size;
+ gtk_widget_adjust_size_allocation (widget, OPPOSITE_ORIENTATION (orientation),
+ &for_size, &natural_for_size,
+ &dummy, &adjusted_for_size);
+
+ adjusted_for_size -= css_extra_for_size;
+
+ push_recursion_check (widget, orientation);
+ widget_class->measure (widget,
+ orientation,
+ adjusted_for_size,
+ &reported_min_size, &reported_nat_size,
+ &min_baseline, &nat_baseline);
+ pop_recursion_check (widget, orientation);
+ }
}
min_size = MAX (0, MAX (reported_min_size, css_min_size)) + css_extra_size;
@@ -512,7 +555,13 @@ gtk_widget_get_request_mode (GtkWidget *widget)
if (G_UNLIKELY (!cache->request_mode_valid))
{
- cache->request_mode = GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget);
+ GtkLayoutManager *layout_manager = gtk_widget_get_layout_manager (widget);
+
+ if (layout_manager != NULL)
+ cache->request_mode = gtk_layout_manager_get_request_mode (layout_manager, widget);
+ else
+ cache->request_mode = GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget);
+
cache->request_mode_valid = TRUE;
}
diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h
index fc58058821..8444999778 100644
--- a/gtk/gtktypes.h
+++ b/gtk/gtktypes.h
@@ -38,6 +38,7 @@ typedef struct _GtkBuilder GtkBuilder;
typedef struct _GtkClipboard GtkClipboard;
typedef struct _GtkEventController GtkEventController;
typedef struct _GtkGesture GtkGesture;
+typedef struct _GtkLayoutManager GtkLayoutManager;
typedef struct _GtkRequisition GtkRequisition;
typedef struct _GtkSelectionData GtkSelectionData;
typedef struct _GtkSettings GtkSettings;
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 4fadd96534..38d6ff9a57 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -47,6 +47,7 @@
#include "gtkgestureswipe.h"
#include "gtkintl.h"
#include "gtkinvisible.h"
+#include "gtklayoutmanagerprivate.h"
#include "gtkmarshalers.h"
#include "gtkmain.h"
#include "gtkmenu.h"
@@ -4257,16 +4258,26 @@ gtk_widget_size_allocate (GtkWidget *widget,
if (baseline >= 0)
baseline -= margin.top + border.top + padding.top;
- if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE))
- g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0,
- real_allocation.width,
- real_allocation.height,
- baseline);
+ if (priv->layout_manager != NULL)
+ {
+ gtk_layout_manager_allocate (priv->layout_manager, widget,
+ real_allocation.width,
+ real_allocation.height,
+ baseline);
+ }
else
- GTK_WIDGET_GET_CLASS (widget)->size_allocate (widget,
- real_allocation.width,
- real_allocation.height,
- baseline);
+ {
+ if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE))
+ g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0,
+ real_allocation.width,
+ real_allocation.height,
+ baseline);
+ else
+ GTK_WIDGET_GET_CLASS (widget)->size_allocate (widget,
+ real_allocation.width,
+ real_allocation.height,
+ baseline);
+ }
/* Size allocation is god... after consulting god, no further requests or allocations are needed */
#ifdef G_ENABLE_DEBUG
@@ -8158,6 +8169,9 @@ gtk_widget_dispose (GObject *object)
while (priv->paintables)
gtk_widget_paintable_set_widget (priv->paintables->data, NULL);
+ gtk_widget_set_layout_manager (widget, NULL);
+ g_clear_object (&priv->layout_manager);
+
priv->visible = FALSE;
if (_gtk_widget_get_realized (widget))
gtk_widget_unrealize (widget);
@@ -13630,3 +13644,47 @@ gtk_widget_get_height (GtkWidget *widget)
border.top - border.bottom -
padding.top - padding.bottom;
}
+
+/**
+ * gtk_widget_set_layout_manager:
+ * @widget: a #GtkWidget
+ * @layout_manager: (nullable): a #GtkLayoutManager
+ *
+ * Sets the layout manager delegate instance that provides an implementation
+ * for measuring and allocating the children of @widget.
+ */
+void
+gtk_widget_set_layout_manager (GtkWidget *widget,
+ GtkLayoutManager *layout_manager)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (layout_manager == NULL || GTK_IS_LAYOUT_MANAGER (layout_manager));
+
+ if (g_set_object (&priv->layout_manager, layout_manager))
+ {
+ if (priv->layout_manager != NULL)
+ gtk_layout_manager_set_widget (priv->layout_manager, widget);
+
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+/**
+ * gtk_widget_get_layout_manager:
+ * @widget: a #GtkWidget
+ *
+ * Retrieves the layout manager set using gtk_widget_set_layout_manager().
+ *
+ * Returns: (transfer none) (nullable): a #GtkLayoutManager
+ */
+GtkLayoutManager *
+gtk_widget_get_layout_manager (GtkWidget *widget)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ return priv->layout_manager;
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 5d6236ea8a..d99dc1aa24 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -424,6 +424,12 @@ void gtk_widget_get_preferred_size (GtkWidget *w
GtkRequisition *minimum_size,
GtkRequisition *natural_size);
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_set_layout_manager (GtkWidget *widget,
+ GtkLayoutManager *layout_manager);
+GDK_AVAILABLE_IN_ALL
+GtkLayoutManager * gtk_widget_get_layout_manager (GtkWidget *widget);
+
GDK_AVAILABLE_IN_ALL
void gtk_widget_add_accelerator (GtkWidget *widget,
const gchar *accel_signal,
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index f658811358..0ac93eace4 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -149,6 +149,9 @@ struct _GtkWidgetPrivate
/* The render node we draw or %NULL if not yet created.*/
GskRenderNode *render_node;
+ /* The layout manager, or %NULL */
+ GtkLayoutManager *layout_manager;
+
GSList *paintables;
/* The widget's surface or its parent surface if it does
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]