diff options
author | Benjamin Otte <otte@redhat.com> | 2023-04-05 15:10:16 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2023-05-09 17:00:39 +0200 |
commit | 81e7e67ceffe44a05822327dfc61d3b78e37f0b9 (patch) | |
tree | 84b436cfb8bfd26f641819f317274ddcef129c67 | |
parent | 35543f60d9ffd2466385cfd911d67044771748a4 (diff) | |
download | gtk+-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.c | 2 | ||||
-rw-r--r-- | gtk/gtklistitemmanager.c | 81 | ||||
-rw-r--r-- | gtk/gtklistitemmanagerprivate.h | 6 |
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); |