listitemmanager: Make sections configurable
authorBenjamin Otte <otte@redhat.com>
Sun, 9 Apr 2023 03:29:14 +0000 (05:29 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 9 May 2023 15:00:40 +0000 (17:00 +0200)
Add a gtk_list_item_manager_set_has_sections() (default: FALSE) that
requires explicit turning on for the listitemmanager to gain section
support.

gtk/gtklistitemmanager.c
gtk/gtklistitemmanagerprivate.h
testsuite/gtk/listitemmanager.c

index 4bd66bc79cd51edcfd653328d75ee98ff55bbcef..a9c15982b3b5bd85db2d1a5e8c70ea0457f54669 100644 (file)
@@ -32,6 +32,7 @@ struct _GtkListItemManager
 
   GtkWidget *widget;
   GtkSelectionModel *model;
+  gboolean has_sections;
 
   GtkRbTree *items;
   GSList *trackers;
@@ -182,7 +183,7 @@ gtk_list_item_manager_new (GtkWidget         *widget,
 static gboolean
 gtk_list_item_manager_has_sections (GtkListItemManager *self)
 {
-  if (self->model == NULL)
+  if (self->model == NULL || !self->has_sections)
     return FALSE;
 
   return GTK_IS_SECTION_MODEL (self->model);
@@ -1566,6 +1567,84 @@ gtk_list_item_manager_get_model (GtkListItemManager *self)
   return self->model;
 }
 
+void
+gtk_list_item_manager_set_has_sections (GtkListItemManager *self,
+                                        gboolean            has_sections)
+{
+  GtkListTile *tile;
+  gboolean had_sections;
+
+  if (self->has_sections == has_sections)
+    return;
+
+  had_sections = gtk_list_item_manager_has_sections (self);
+
+  self->has_sections = has_sections;
+
+  if (!had_sections && gtk_list_item_manager_has_sections (self))
+    {
+      tile = gtk_rb_tree_get_first (self->items);
+      if (tile && tile->type != GTK_LIST_TILE_HEADER && tile->type != GTK_LIST_TILE_UNMATCHED_HEADER)
+        tile = gtk_list_tile_get_next_skip (tile);
+      if (tile)
+        gtk_list_tile_set_type (tile, GTK_LIST_TILE_UNMATCHED_HEADER);
+
+      tile = gtk_rb_tree_get_last (self->items);
+      if (tile && tile->type != GTK_LIST_TILE_FOOTER && tile->type != GTK_LIST_TILE_UNMATCHED_FOOTER)
+        tile = gtk_list_tile_get_previous_skip (tile);
+      if (tile)
+        gtk_list_tile_set_type (tile, GTK_LIST_TILE_UNMATCHED_FOOTER);
+    }
+  else if (had_sections && !gtk_list_item_manager_has_sections (self))
+    {
+      GtkListTile *header = NULL, *footer = NULL;
+
+      for (tile = gtk_rb_tree_get_first (self->items);
+           tile;
+           tile = gtk_list_tile_get_next_skip (tile))
+        {
+          switch (tile->type)
+            {
+            case GTK_LIST_TILE_HEADER:
+            case GTK_LIST_TILE_UNMATCHED_HEADER:
+              if (!header)
+                header = tile;
+              else
+                gtk_list_tile_set_type (tile, GTK_LIST_TILE_REMOVED);
+              break;
+            case GTK_LIST_TILE_FOOTER:
+            case GTK_LIST_TILE_UNMATCHED_FOOTER:
+              if (footer)
+                gtk_list_tile_set_type (footer, GTK_LIST_TILE_REMOVED);
+              footer = tile;
+              break;
+            case GTK_LIST_TILE_ITEM:
+            case GTK_LIST_TILE_FILLER:
+            case GTK_LIST_TILE_REMOVED:
+              break;
+            default:
+              g_assert_not_reached ();
+              break;
+            }
+        }
+      if (header)
+        {
+          gtk_list_tile_set_type (header, GTK_LIST_TILE_HEADER);
+          gtk_list_tile_set_type (footer, GTK_LIST_TILE_FOOTER);
+        }
+    }
+
+  gtk_list_item_manager_ensure_items (self, NULL, G_MAXUINT);
+
+  gtk_widget_queue_resize (self->widget);
+}
+
+gboolean
+gtk_list_item_manager_get_has_sections (GtkListItemManager *self)
+{
+  return self->has_sections;
+}
+
 /*
  * gtk_list_item_manager_acquire_list_item:
  * @self: a `GtkListItemManager`
index 5094ad4e9973b066e7de91e3fbf9b4b22cb853a0..29d24a4925d36dfeb27e5df86c0e92ba35171d16 100644 (file)
@@ -121,6 +121,9 @@ GtkListTile *           gtk_list_tile_gc                        (GtkListItemMana
 void                    gtk_list_item_manager_set_model         (GtkListItemManager     *self,
                                                                  GtkSelectionModel      *model);
 GtkSelectionModel *     gtk_list_item_manager_get_model         (GtkListItemManager     *self);
+void                    gtk_list_item_manager_set_has_sections  (GtkListItemManager     *self,
+                                                                 gboolean                has_sections);
+gboolean                gtk_list_item_manager_get_has_sections  (GtkListItemManager     *self);
 
 GtkListItemTracker *    gtk_list_item_tracker_new               (GtkListItemManager     *self);
 void                    gtk_list_item_tracker_free              (GtkListItemManager     *self,
index 9173d5e7084a65e448c48140bcf4d3b4d194dd93..828a2817456776ce3a5017b92f6fc07a8097564f 100644 (file)
@@ -372,7 +372,7 @@ test_exhaustive (void)
       if (g_test_verbose ())
         print_list_item_manager_tiles (items);
 
-      switch (g_test_rand_int_range (0, 5))
+      switch (g_test_rand_int_range (0, 6))
       {
         case 0:
           if (g_test_verbose ())
@@ -413,6 +413,15 @@ test_exhaustive (void)
             }
           break;
 
+        case 5:
+          {
+            gboolean has_sections = g_test_rand_bit ();
+            if (g_test_verbose ())
+              g_test_message ("Setting has_sections to %s", has_sections ? "true" : "false");
+            gtk_list_item_manager_set_has_sections (items, has_sections);
+          }
+          break;
+
         default:
           g_assert_not_reached ();
           break;