summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2023-04-05 15:10:16 +0200
committerBenjamin Otte <otte@redhat.com>2023-05-09 17:00:39 +0200
commit81e7e67ceffe44a05822327dfc61d3b78e37f0b9 (patch)
tree84b436cfb8bfd26f641819f317274ddcef129c67
parent35543f60d9ffd2466385cfd911d67044771748a4 (diff)
downloadgtk+-81e7e67ceffe44a05822327dfc61d3b78e37f0b9.tar.gz
listitemmanager: Add tile types
We have a FILLER and a REMOVED type now. Also makes gc() more sensitive to types.
-rw-r--r--gtk/gtkgridview.c2
-rw-r--r--gtk/gtklistitemmanager.c81
-rw-r--r--gtk/gtklistitemmanagerprivate.h6
3 files changed, 76 insertions, 13 deletions
diff --git a/gtk/gtkgridview.c b/gtk/gtkgridview.c
index ead43a8c8b..6299766c2f 100644
--- a/gtk/gtkgridview.c
+++ b/gtk/gtkgridview.c
@@ -886,7 +886,7 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
{
GtkListTile *filler;
tile = gtk_list_item_manager_get_last (self->item_manager);
- filler = gtk_list_tile_split (self->item_manager, tile, tile->n_items);
+ filler = gtk_list_tile_append_filler (self->item_manager, tile);
gtk_list_tile_set_area_position (self->item_manager,
filler,
column_start (self, xspacing, i),
diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c
index e73b1512bf..f976b0063e 100644
--- a/gtk/gtklistitemmanager.c
+++ b/gtk/gtklistitemmanager.c
@@ -597,6 +597,7 @@ gtk_list_item_manager_remove_items (GtkListItemManager *self,
tile->widget = NULL;
n_items -= tile->n_items;
tile->n_items = 0;
+ tile->type = GTK_LIST_TILE_REMOVED;
gtk_rb_tree_node_mark_dirty (tile);
tile = next;
@@ -655,7 +656,7 @@ gtk_list_item_manager_merge_list_items (GtkListItemManager *self,
* items will be given to the new tile, which will be
* nserted after the tile.
*
- * It is valid for either tile to have 0 items after
+ * It is not valid for either tile to have 0 items after
* the split.
*
* Returns: The new tile
@@ -667,7 +668,8 @@ gtk_list_tile_split (GtkListItemManager *self,
{
GtkListTile *result;
- g_assert (n_items <= tile->n_items);
+ g_assert (n_items > 0);
+ g_assert (n_items < tile->n_items);
g_assert (tile->type == GTK_LIST_TILE_ITEM);
result = gtk_rb_tree_insert_after (self->items, tile);
@@ -680,9 +682,37 @@ gtk_list_tile_split (GtkListItemManager *self,
}
/*
+ * gtk_list_tile_append_filler:
+ * @self: the listitemmanager
+ * @previous: tile to append to
+ *
+ * Appends a filler tile.
+ *
+ * Filler tiles don't refer to any items or header and exist
+ * just to take up space, so that finding items by position gets
+ * easier.
+ *
+ * They ave a special garbage-collection behavior, see
+ * gtk_list_tile_gc().
+ *
+ * Returns: The new filler tile
+ **/
+GtkListTile *
+gtk_list_tile_append_filler (GtkListItemManager *self,
+ GtkListTile *previous)
+{
+ GtkListTile *result;
+
+ result = gtk_rb_tree_insert_after (self->items, previous);
+ result->type = GTK_LIST_TILE_FILLER;
+
+ return result;
+}
+
+/*
* gtk_list_tile_gc:
* @self: the listitemmanager
- * @tile: a tile
+ * @tile: a tile or NULL
*
* Tries to get rid of tiles when they aren't needed anymore,
* either because their referenced listitems were deleted or
@@ -690,7 +720,11 @@ gtk_list_tile_split (GtkListItemManager *self,
*
* Note that this only looks forward, but never backward.
*
- * Returns: The next tile
+ * A special case here are filler tiles. They only get
+ * collected, when they are explicitly passed in, but never
+ * otherwise.
+ *
+ * Returns: The next tile or NULL if everything was gc'ed
**/
GtkListTile *
gtk_list_tile_gc (GtkListItemManager *self,
@@ -698,22 +732,47 @@ gtk_list_tile_gc (GtkListItemManager *self,
{
GtkListTile *next;
+ if (tile == NULL)
+ return NULL;
+
+ if (tile->type == GTK_LIST_TILE_FILLER)
+ {
+ next = gtk_rb_tree_node_get_next (tile);
+ gtk_rb_tree_remove (self->items, tile);
+ tile = next;
+ }
+
while (tile)
{
next = gtk_rb_tree_node_get_next (tile);
+ while (next && next->type == GTK_LIST_TILE_REMOVED)
+ {
+ gtk_rb_tree_remove (self->items, next);
+ next = gtk_rb_tree_node_get_next (tile);
+ }
- if (tile->n_items == 0)
+ switch (tile->type)
{
+ case GTK_LIST_TILE_ITEM:
+ g_assert (tile->n_items > 0);
+ if (next == NULL)
+ break;
+ if (gtk_list_item_manager_merge_list_items (self, tile, next))
+ continue;
+ break;
+
+ case GTK_LIST_TILE_FILLER:
+ break;
+
+ case GTK_LIST_TILE_REMOVED:
gtk_rb_tree_remove (self->items, tile);
tile = next;
continue;
- }
-
- if (next == NULL)
- break;
- if (gtk_list_item_manager_merge_list_items (self, tile, next))
- continue;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
break;
}
diff --git a/gtk/gtklistitemmanagerprivate.h b/gtk/gtklistitemmanagerprivate.h
index a82e686266..df6e0d1211 100644
--- a/gtk/gtklistitemmanagerprivate.h
+++ b/gtk/gtklistitemmanagerprivate.h
@@ -45,7 +45,9 @@ typedef struct _GtkListItemTracker GtkListItemTracker;
typedef enum
{
- GTK_LIST_TILE_ITEM
+ GTK_LIST_TILE_ITEM,
+ GTK_LIST_TILE_FILLER,
+ GTK_LIST_TILE_REMOVED,
} GtkListTileType;
struct _GtkListTile
@@ -103,6 +105,8 @@ void gtk_list_tile_set_area_size (GtkListItemMana
GtkListTile * gtk_list_tile_split (GtkListItemManager *self,
GtkListTile *tile,
guint n_items);
+GtkListTile * gtk_list_tile_append_filler (GtkListItemManager *self,
+ GtkListTile *previous);
GtkListTile * gtk_list_tile_gc (GtkListItemManager *self,
GtkListTile *tile);