listitemmanager: Add tile types

We have a FILLER and a REMOVED type now.

Also makes gc() more sensitive to types.
This commit is contained in:
Benjamin Otte
2023-04-05 15:10:16 +02:00
parent 35543f60d9
commit 81e7e67cef
3 changed files with 77 additions and 14 deletions

View File

@@ -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),

View File

@@ -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);
@@ -679,10 +681,38 @@ gtk_list_tile_split (GtkListItemManager *self,
return result;
}
/*
* 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,23 +732,48 @@ 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);
if (tile->n_items == 0)
while (next && next->type == GTK_LIST_TILE_REMOVED)
{
gtk_rb_tree_remove (self->items, next);
next = gtk_rb_tree_node_get_next (tile);
}
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;
default:
g_assert_not_reached ();
break;
}
if (next == NULL)
break;
if (gtk_list_item_manager_merge_list_items (self, tile, next))
continue;
break;
}

View File

@@ -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);