[gtk/stack-fixes] stack: Manage children model ourselves
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/stack-fixes] stack: Manage children model ourselves
- Date: Sun, 10 Feb 2019 01:12:56 +0000 (UTC)
commit a5d6156f4e14cd2d7c3d28470e27cc1d72e71142
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Feb 9 20:08:12 2019 -0500
stack: Manage children model ourselves
Instead of relying on the debug functionality of
gtk_widget_observe_children, create our own model
for children. This has the advantage that we can
control when it gets emptied in dispose, and avoid
ordering problems with signals getting emitted
halfway through dispose.
gtk/gtkstack.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 42 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index 0da9f006ff..96b6ad1283 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -31,6 +31,7 @@
#include "gtksnapshot.h"
#include "gtkwidgetprivate.h"
#include "gtksingleselection.h"
+#include "gtklistlistmodelprivate.h"
#include "a11y/gtkstackaccessible.h"
#include "a11y/gtkstackaccessibleprivate.h"
#include <math.h>
@@ -140,6 +141,7 @@ typedef struct {
GtkStackTransitionType active_transition_type;
GtkSelectionModel *pages;
+ GBinding *binding;
} GtkStackPrivate;
@@ -453,6 +455,15 @@ remove_child (GtkWidget *child, gpointer user_data)
static void
gtk_stack_dispose (GObject *obj)
{
+ GtkStack *stack = GTK_STACK (obj);
+ GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+
+ g_clear_pointer (&priv->binding, g_binding_unbind);
+ if (priv->pages)
+ {
+ GListModel *children = gtk_selection_model_get_model (priv->pages);
+ gtk_list_list_model_clear (GTK_LIST_LIST_MODEL (children));
+ }
gtk_container_foreach (GTK_CONTAINER (obj), remove_child, obj);
G_OBJECT_CLASS (gtk_stack_parent_class)->dispose (obj);
@@ -1221,6 +1232,12 @@ gtk_stack_add_page (GtkStack *stack,
gtk_widget_set_child_visible (child_info->widget, FALSE);
gtk_widget_set_parent (child_info->widget, GTK_WIDGET (stack));
+ if (priv->pages)
+ {
+ GListModel *children = gtk_selection_model_get_model (priv->pages);
+ gtk_list_list_model_item_added (GTK_LIST_LIST_MODEL (children), child_info->widget);
+ }
+
g_signal_connect (child_info->widget, "notify::visible",
G_CALLBACK (stack_child_visibility_notify_cb), stack);
@@ -1280,7 +1297,16 @@ static void
gtk_stack_remove (GtkContainer *container,
GtkWidget *child)
{
+ GtkStackPrivate *priv = gtk_stack_get_instance_private (GTK_STACK (container));
+ GtkWidget *prev_sibling = gtk_widget_get_prev_sibling (child);
+
stack_remove (GTK_STACK (container), child, FALSE);
+
+ if (priv->pages)
+ {
+ GListModel *children = gtk_selection_model_get_model (priv->pages);
+ gtk_list_list_model_item_removed (GTK_LIST_LIST_MODEL (children), prev_sibling);
+ }
}
/**
@@ -2313,18 +2339,29 @@ GtkSelectionModel *
gtk_stack_get_pages (GtkStack *stack)
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+ GListModel *children;
g_return_val_if_fail (GTK_IS_STACK (stack), NULL);
if (priv->pages)
return g_object_ref (priv->pages);
- priv->pages = GTK_SELECTION_MODEL (gtk_single_selection_new (gtk_widget_observe_children (GTK_WIDGET
(stack))));
+ children = G_LIST_MODEL (gtk_list_list_model_new (GTK_TYPE_WIDGET,
+ (gpointer) gtk_widget_get_first_child,
+ (gpointer) gtk_widget_get_next_sibling,
+ (gpointer) gtk_widget_get_prev_sibling,
+ (gpointer) gtk_widget_get_last_child,
+ (gpointer) g_object_ref,
+ stack, NULL));
+ priv->pages = GTK_SELECTION_MODEL (gtk_single_selection_new (children));
+ g_object_unref (children);
+
g_object_add_weak_pointer (G_OBJECT (priv->pages), (gpointer *)&priv->pages);
- g_object_bind_property_full (stack, "visible-child",
- priv->pages, "selected",
- G_BINDING_BIDIRECTIONAL|G_BINDING_SYNC_CREATE,
- transform_to, transform_from, stack, NULL);
+ priv->binding = g_object_bind_property_full (stack, "visible-child",
+ priv->pages, "selected",
+ G_BINDING_BIDIRECTIONAL|G_BINDING_SYNC_CREATE,
+ transform_to, transform_from, stack, NULL);
+ g_object_add_weak_pointer (G_OBJECT (priv->binding), (gpointer *)&priv->binding);
return priv->pages;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]