columnview: Implement inertness
authorBenjamin Otte <otte@redhat.com>
Wed, 29 Mar 2023 08:33:51 +0000 (10:33 +0200)
committerBenjamin Otte <otte@redhat.com>
Sat, 1 Apr 2023 18:49:40 +0000 (20:49 +0200)
This properly implements the same behavior as
62e9d1e470b0819bdcb4d2a3ba05e083306fc0da and avoids randomly losing
factories.

Oops.

gtk/gtkcolumnview.c
gtk/gtkcolumnviewcellwidget.c
gtk/gtkcolumnviewcellwidgetprivate.h
gtk/gtkcolumnviewcolumn.c
gtk/gtkcolumnviewcolumnprivate.h
gtk/gtkcolumnviewprivate.h
gtk/gtkcolumnviewrowwidget.c
gtk/gtkcolumnviewrowwidgetprivate.h

index 8a87acb9c66d268386f52df778ab9ed037c37937..addb92ef32c8749b7b5f6ea2cc324b253a460a29 100644 (file)
@@ -179,7 +179,7 @@ gtk_column_list_view_create_list_widget (GtkListBase *base)
   GtkWidget *result;
   guint i;
 
-  result = gtk_column_view_row_widget_new (FALSE);
+  result = gtk_column_view_row_widget_new (gtk_list_view_get_factory (self->listview), FALSE);
 
   gtk_list_factory_widget_set_single_click_activate (GTK_LIST_FACTORY_WIDGET (result), GTK_LIST_VIEW (base)->single_click_activate);
 
@@ -191,7 +191,7 @@ gtk_column_list_view_create_list_widget (GtkListBase *base)
         {
           GtkWidget *cell;
 
-          cell = gtk_column_view_cell_widget_new (column);
+          cell = gtk_column_view_cell_widget_new (column, gtk_column_view_is_inert (self));
           gtk_column_view_row_widget_add_child (GTK_COLUMN_VIEW_ROW_WIDGET (result), cell);
         }
 
@@ -297,6 +297,31 @@ G_DEFINE_TYPE_WITH_CODE (GtkColumnView, gtk_column_view, GTK_TYPE_WIDGET,
 static GParamSpec *properties[N_PROPS] = { NULL, };
 static guint signals[LAST_SIGNAL] = { 0 };
 
+gboolean
+gtk_column_view_is_inert (GtkColumnView *self)
+{
+  GtkWidget *widget = GTK_WIDGET (self);
+
+  return !gtk_widget_get_visible (widget) ||
+         gtk_widget_get_root (widget) == NULL;
+}
+
+static void
+gtk_column_view_update_cell_factories (GtkColumnView *self,
+                                       gboolean       inert)
+{
+  guint i, n;
+
+  n = g_list_model_get_n_items (G_LIST_MODEL (self->columns));
+
+  for (i = 0; i < n; i++)
+    {
+      GtkColumnViewColumn *column = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
+
+      gtk_column_view_column_update_factory (column, inert);
+    }
+}
+
 static void
 gtk_column_view_measure (GtkWidget      *widget,
                          GtkOrientation  orientation,
@@ -475,6 +500,50 @@ gtk_column_view_allocate (GtkWidget *widget,
   gtk_adjustment_configure (self->hadjustment,  x, 0, full_width, width * 0.1, width * 0.9, width);
 }
 
+static void
+gtk_column_view_root (GtkWidget *widget)
+{
+  GtkColumnView *self = GTK_COLUMN_VIEW (widget);
+
+  GTK_WIDGET_CLASS (gtk_column_view_parent_class)->root (widget);
+
+  if (!gtk_column_view_is_inert (self))
+    gtk_column_view_update_cell_factories (self, FALSE);
+}
+
+static void
+gtk_column_view_unroot (GtkWidget *widget)
+{
+  GtkColumnView *self = GTK_COLUMN_VIEW (widget);
+
+  if (!gtk_column_view_is_inert (self))
+    gtk_column_view_update_cell_factories (self, TRUE);
+
+  GTK_WIDGET_CLASS (gtk_column_view_parent_class)->unroot (widget);
+}
+
+static void
+gtk_column_view_show (GtkWidget *widget)
+{
+  GtkColumnView *self = GTK_COLUMN_VIEW (widget);
+
+  GTK_WIDGET_CLASS (gtk_column_view_parent_class)->show (widget);
+
+  if (!gtk_column_view_is_inert (self))
+    gtk_column_view_update_cell_factories (self, FALSE);
+}
+
+static void
+gtk_column_view_hide (GtkWidget *widget)
+{
+  GtkColumnView *self = GTK_COLUMN_VIEW (widget);
+
+  if (!gtk_column_view_is_inert (self))
+    gtk_column_view_update_cell_factories (self, TRUE);
+
+  GTK_WIDGET_CLASS (gtk_column_view_parent_class)->hide (widget);
+}
+
 static void
 gtk_column_view_activate_cb (GtkListView   *listview,
                              guint          pos,
@@ -702,6 +771,10 @@ gtk_column_view_class_init (GtkColumnViewClass *klass)
   widget_class->grab_focus = gtk_widget_grab_focus_child;
   widget_class->measure = gtk_column_view_measure;
   widget_class->size_allocate = gtk_column_view_allocate;
+  widget_class->root = gtk_column_view_root;
+  widget_class->unroot = gtk_column_view_unroot;
+  widget_class->show = gtk_column_view_show;
+  widget_class->hide = gtk_column_view_hide;
 
   gobject_class->dispose = gtk_column_view_dispose;
   gobject_class->finalize = gtk_column_view_finalize;
@@ -1329,7 +1402,7 @@ gtk_column_view_init (GtkColumnView *self)
 
   self->columns = g_list_store_new (GTK_TYPE_COLUMN_VIEW_COLUMN);
 
-  self->header = gtk_column_view_row_widget_new (TRUE);
+  self->header = gtk_column_view_row_widget_new (NULL, TRUE);
   gtk_widget_set_can_focus (self->header, FALSE);
   gtk_widget_set_parent (self->header, GTK_WIDGET (self));
 
index 11c0a78188209ed792f2d167a7e195e995a3eea2..7464a3c3f6403bc3eea8c8652b41f66d160116b1 100644 (file)
@@ -237,12 +237,13 @@ gtk_column_view_cell_widget_init (GtkColumnViewCellWidget *self)
 }
 
 GtkWidget *
-gtk_column_view_cell_widget_new (GtkColumnViewColumn *column)
+gtk_column_view_cell_widget_new (GtkColumnViewColumn *column,
+                                 gboolean             inert)
 {
   GtkColumnViewCellWidget *self;
 
   self = g_object_new (GTK_TYPE_COLUMN_VIEW_CELL_WIDGET,
-                       "factory", gtk_column_view_column_get_factory (column),
+                       "factory", inert ? NULL : gtk_column_view_column_get_factory (column),
                        NULL);
 
   self->column = g_object_ref (column);
index 4e8f3a677a3ff263c6c70f2326713a2a37c08753..b50e69e477d94f91aeb2021a7451b8d267a175d8 100644 (file)
@@ -35,7 +35,8 @@ typedef struct _GtkColumnViewCellWidgetClass GtkColumnViewCellWidgetClass;
 
 GType                           gtk_column_view_cell_widget_get_type           (void) G_GNUC_CONST;
 
-GtkWidget *                     gtk_column_view_cell_widget_new                (GtkColumnViewColumn             *column);
+GtkWidget *                     gtk_column_view_cell_widget_new                (GtkColumnViewColumn             *column,
+                                                                                gboolean                         inert);
 
 void                            gtk_column_view_cell_widget_remove             (GtkColumnViewCellWidget         *self);
 
index 4027f87f2d8b52b7b3df1cf19510778742872fc7..32d8e1d56211e331d62d57dc94269a7bc0682c9b 100644 (file)
@@ -532,12 +532,9 @@ gtk_column_view_column_create_cells (GtkColumnViewColumn *self)
       GtkListItemBase *base;
       GtkWidget *cell;
 
-      if (!gtk_widget_get_root (row))
-        continue;
-
       list_item = GTK_COLUMN_VIEW_ROW_WIDGET (row);
       base = GTK_LIST_ITEM_BASE (row);
-      cell = gtk_column_view_cell_widget_new (self);
+      cell = gtk_column_view_cell_widget_new (self, gtk_column_view_is_inert (self->view));
       gtk_column_view_row_widget_add_child (list_item, cell);
       gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell),
                                  gtk_list_item_base_get_position (base),
@@ -581,8 +578,7 @@ gtk_column_view_column_remove_header (GtkColumnViewColumn *self)
 static void
 gtk_column_view_column_ensure_cells (GtkColumnViewColumn *self)
 {
-  if (self->view && gtk_widget_get_root (GTK_WIDGET (self->view)) &&
-      gtk_column_view_column_get_visible (self))
+  if (self->view && gtk_column_view_column_get_visible (self))
     gtk_column_view_column_create_cells (self);
   else
     gtk_column_view_column_remove_cells (self);
@@ -664,6 +660,29 @@ gtk_column_view_column_get_factory (GtkColumnViewColumn *self)
   return self->factory;
 }
 
+void
+gtk_column_view_column_update_factory (GtkColumnViewColumn *self,
+                                       gboolean             inert)
+{
+  GtkListItemFactory *factory;
+  GtkColumnViewCellWidget *cell;
+
+  if (self->factory == NULL)
+    return;
+
+  if (inert)
+    factory = NULL;
+  else
+    factory = self->factory;
+
+  for (cell = self->first_cell;
+       cell;
+       cell = gtk_column_view_cell_widget_get_next (cell))
+    {
+      gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (cell), factory);
+    }
+}
+
 /**
  * gtk_column_view_column_set_factory: (attributes org.gtk.Method.set_property=factory)
  * @self: a `GtkColumnViewColumn`
@@ -679,9 +698,15 @@ gtk_column_view_column_set_factory (GtkColumnViewColumn *self,
   g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
   g_return_if_fail (factory == NULL || GTK_LIST_ITEM_FACTORY (factory));
 
+  if (self->factory && !factory)
+    gtk_column_view_column_update_factory (self, TRUE);
+
   if (!g_set_object (&self->factory, factory))
     return;
 
+  if (self->view && !gtk_column_view_is_inert (self->view))
+    gtk_column_view_column_update_factory (self, FALSE);
+
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]);
 }
 
index 13b5680886c0187c6631c9136c8a6a0f0d6143cd..fa0c66b2b502dd1dd35b8c96c10f231480018377 100644 (file)
@@ -37,6 +37,8 @@ void                    gtk_column_view_column_remove_cell              (GtkColu
 GtkColumnViewCellWidget *     gtk_column_view_column_get_first_cell           (GtkColumnViewColumn    *self);
 GtkWidget *             gtk_column_view_column_get_header               (GtkColumnViewColumn    *self);
 
+void                    gtk_column_view_column_update_factory           (GtkColumnViewColumn    *self,
+                                                                         gboolean                inert);
 void                    gtk_column_view_column_queue_resize             (GtkColumnViewColumn    *self);
 void                    gtk_column_view_column_measure                  (GtkColumnViewColumn    *self,
                                                                          int                    *minimum,
index 679b582aedbc95fdc02bc468900541766298f6c7..1a3061e332833b2b00a9b458270e17572054fcba 100644 (file)
@@ -26,6 +26,8 @@
 #include "gtk/gtkcolumnviewsorterprivate.h"
 #include "gtk/gtkcolumnviewrowwidgetprivate.h"
 
+gboolean                gtk_column_view_is_inert                (GtkColumnView          *self);
+
 GtkColumnViewRowWidget *gtk_column_view_get_header_widget       (GtkColumnView          *self);
 GtkListView *           gtk_column_view_get_list_view           (GtkColumnView          *self);
 
index fe2b290f57212b364aa08481035da61f56a5725b..62cec81b0e07c4c6ad29c5acfe10ae971d9d5287 100644 (file)
@@ -532,9 +532,11 @@ gtk_column_view_row_widget_init (GtkColumnViewRowWidget *self)
 }
 
 GtkWidget *
-gtk_column_view_row_widget_new (gboolean is_header)
+gtk_column_view_row_widget_new (GtkListItemFactory *factory,
+                                gboolean            is_header)
 {
   return g_object_new (GTK_TYPE_COLUMN_VIEW_ROW_WIDGET,
+                       "factory", factory,
                        "css-name", is_header ? "header" : "row",
                        "selectable", TRUE,
                        "activatable", TRUE,
index 5cc4aa1dadbcdba928544ad13b7a202a0fd6d293..4174fb8601f160e516658575939ac2433c5aa1b3 100644 (file)
@@ -45,7 +45,8 @@ struct _GtkColumnViewRowWidgetClass
 
 GType                   gtk_column_view_row_widget_get_type             (void) G_GNUC_CONST;
 
-GtkWidget *             gtk_column_view_row_widget_new                  (gboolean                is_header);
+GtkWidget *             gtk_column_view_row_widget_new                  (GtkListItemFactory     *factory,
+                                                                         gboolean                is_header);
 
 void                    gtk_column_view_row_widget_add_child            (GtkColumnViewRowWidget *self,
                                                                          GtkWidget              *child);