listitemmanager: Add section tiles

For now, we just have a HEADER at the start and a FOOTER at the end.
That's hard enough to get right.
This commit is contained in:
Benjamin Otte 2023-04-07 04:00:00 +02:00
parent cecaede610
commit e680abc723
3 changed files with 82 additions and 0 deletions

View File

@ -132,6 +132,7 @@ gtk_list_item_manager_new (GtkWidget *widget,
GtkListItemBase * (* create_widget) (GtkWidget *))
{
GtkListItemManager *self;
GtkListTile *header, *footer;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
@ -148,6 +149,12 @@ gtk_list_item_manager_new (GtkWidget *widget,
gtk_list_item_manager_clear_node,
NULL);
header = gtk_rb_tree_insert_after (self->items, NULL);
header->type = GTK_LIST_TILE_HEADER;
footer = gtk_rb_tree_insert_before (self->items, NULL);
footer->type = GTK_LIST_TILE_FOOTER;
return self;
}
@ -618,6 +625,8 @@ gtk_list_item_manager_add_items (GtkListItemManager *self,
return;
tile = gtk_list_item_manager_get_nth (self, position, &offset);
if (tile == NULL)
tile = gtk_rb_tree_get_last (self->items);
if (offset)
tile = gtk_list_item_manager_ensure_split (self, tile, offset);
@ -761,6 +770,10 @@ gtk_list_tile_gc (GtkListItemManager *self,
continue;
break;
case GTK_LIST_TILE_HEADER:
case GTK_LIST_TILE_FOOTER:
case GTK_LIST_TILE_UNMATCHED_HEADER:
case GTK_LIST_TILE_UNMATCHED_FOOTER:
case GTK_LIST_TILE_FILLER:
break;

View File

@ -46,6 +46,10 @@ typedef struct _GtkListItemTracker GtkListItemTracker;
typedef enum
{
GTK_LIST_TILE_ITEM,
GTK_LIST_TILE_HEADER,
GTK_LIST_TILE_FOOTER,
GTK_LIST_TILE_UNMATCHED_HEADER,
GTK_LIST_TILE_UNMATCHED_FOOTER,
GTK_LIST_TILE_FILLER,
GTK_LIST_TILE_REMOVED,
} GtkListTileType;

View File

@ -45,6 +45,11 @@ check_list_item_manager (GtkListItemManager *items,
GtkListTile *tile;
guint n_items = 0;
guint i;
enum {
NO_SECTION,
MATCHED_SECTION,
UNMATCHED_SECTION
} section_state = NO_SECTION;
for (tile = gtk_list_item_manager_get_first (items);
tile != NULL;
@ -52,7 +57,36 @@ check_list_item_manager (GtkListItemManager *items,
{
switch (tile->type)
{
case GTK_LIST_TILE_HEADER:
g_assert_cmpint (section_state, ==, NO_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = MATCHED_SECTION;
break;
case GTK_LIST_TILE_UNMATCHED_HEADER:
g_assert_cmpint (section_state, ==, NO_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = UNMATCHED_SECTION;
break;
case GTK_LIST_TILE_FOOTER:
g_assert_cmpint (section_state, ==, MATCHED_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = NO_SECTION;
break;
case GTK_LIST_TILE_UNMATCHED_FOOTER:
g_assert_cmpint (section_state, ==, UNMATCHED_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = NO_SECTION;
break;
case GTK_LIST_TILE_ITEM:
g_assert_cmpint (section_state, !=, NO_SECTION);
if (tile->widget)
{
GObject *item = g_list_model_get_item (model, n_items);
@ -81,6 +115,7 @@ check_list_item_manager (GtkListItemManager *items,
}
}
g_assert_cmpint (section_state, ==, NO_SECTION);
g_assert_cmpint (n_items, ==, g_list_model_get_n_items (model));
for (i = 0; i < n_trackers; i++)
@ -109,7 +144,36 @@ check_list_item_manager (GtkListItemManager *items,
{
switch (tile->type)
{
case GTK_LIST_TILE_HEADER:
g_assert_cmpint (section_state, ==, NO_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = MATCHED_SECTION;
break;
case GTK_LIST_TILE_UNMATCHED_HEADER:
g_assert_cmpint (section_state, ==, NO_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = UNMATCHED_SECTION;
break;
case GTK_LIST_TILE_FOOTER:
g_assert_cmpint (section_state, ==, MATCHED_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = NO_SECTION;
break;
case GTK_LIST_TILE_UNMATCHED_FOOTER:
g_assert_cmpint (section_state, ==, UNMATCHED_SECTION);
g_assert_cmpint (tile->n_items, ==, 0);
g_assert_false (tile->widget);
section_state = NO_SECTION;
break;
case GTK_LIST_TILE_ITEM:
g_assert_cmpint (section_state, !=, NO_SECTION);
if (tile->widget)
{
g_assert_cmpint (tile->n_items, ==, 1);
@ -126,6 +190,7 @@ check_list_item_manager (GtkListItemManager *items,
}
}
g_assert_cmpint (section_state, ==, NO_SECTION);
g_assert_cmpint (n_items, ==, g_list_model_get_n_items (model));
for (i = 0; i < n_trackers; i++)