[gtk/wip/otte/listview: 29/29] gridview: Rework section handling
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 29/29] gridview: Rework section handling
- Date: Sat, 26 Feb 2022 23:52:06 +0000 (UTC)
commit 4309b56b6c7db40c2072cce9a3d53b8187e00407
Author: Benjamin Otte <otte redhat com>
Date: Sun Feb 27 00:28:01 2022 +0100
gridview: Rework section handling
Instead of having custom SECTION blocks, assign the section area to the
cell(s) below. That way navigating to those cells will ensure the
section header is included, which is particularly useful when scrolling.
gtk/gtkgridview.c | 203 +++++++++++++++++++++++++++++-------------------------
1 file changed, 111 insertions(+), 92 deletions(-)
---
diff --git a/gtk/gtkgridview.c b/gtk/gtkgridview.c
index 7e0a14f0f3..f7888571a7 100644
--- a/gtk/gtkgridview.c
+++ b/gtk/gtkgridview.c
@@ -109,11 +109,6 @@ struct _Cell
enum {
/* A newly created cell that hasn't yet been allocated */
UNKNOWN,
- /* A section header.
- * A 0-size cell, the section header widget is in the next
- * cell (sorry, the list item manager needs that).
- */
- SECTION,
/* One or more cells in the same row.
* May contain a widget, but don't have to.
*/
@@ -130,6 +125,7 @@ struct _Cell
FILLER
} cell_type;
int height;
+ int section_height;
int col_start;
int col_end;
};
@@ -249,7 +245,7 @@ static inline int
cell_height (GtkGridView *self,
Cell *cell)
{
- return cell->height;
+ return cell->section_height + cell->height;
}
static void G_GNUC_UNUSED
@@ -297,6 +293,13 @@ dump (GtkGridView *self,
case CELL:
if (cell->parent.widget)
gtk_snapshot_append_color (snapshot, &GDK_RGBA("FFFFFF"), &r.bounds);
+ if (cell->section_height)
+ gtk_snapshot_append_color (snapshot,
+ &GDK_RGBA("7F7F00"),
+ &GRAPHENE_RECT_INIT (r.bounds.origin.x,
+ r.bounds.origin.y,
+ r.bounds.size.width,
+ cell->section_height));
gtk_snapshot_append_border (snapshot,
&r,
@@ -306,15 +309,6 @@ dump (GtkGridView *self,
y += cell_height (self, cell);
break;
- case SECTION:
- gtk_snapshot_append_color (snapshot, &GDK_RGBA("FFFFFF"), &r.bounds);
- gtk_snapshot_append_border (snapshot,
- &r,
- (float[4]) { scale, scale, scale, scale },
- (GdkRGBA[4]) { black, black, black, black });
- y += cell_height (self, cell);
- break;
-
case FILLER:
gtk_snapshot_push_repeat (snapshot, &r.bounds, &GRAPHENE_RECT_INIT (0, 0, 2 * scale, 2 * scale));
gtk_snapshot_append_color (snapshot, &black, &GRAPHENE_RECT_INIT (0, 0, scale, scale));
@@ -327,6 +321,13 @@ dump (GtkGridView *self,
break;
case BLOCK:
+ if (cell->section_height)
+ gtk_snapshot_append_color (snapshot,
+ &GDK_RGBA("7F7F00"),
+ &GRAPHENE_RECT_INIT (r.bounds.origin.x,
+ r.bounds.origin.y,
+ r.bounds.size.width,
+ cell->section_height));
gtk_snapshot_append_border (snapshot,
&r,
(float[4]) { scale, scale, scale, scale },
@@ -379,11 +380,11 @@ cell_augment (GtkRbTree *tree,
aug->height = left_aug->height;
aug->col_start = left_aug->col_start;
if (cell->col_start == 0)
- aug->height += cell->height;
+ aug->height += cell->section_height + cell->height;
}
else
{
- aug->height = cell->height;
+ aug->height = cell->section_height + cell->height;
aug->col_start = cell->col_start;
}
@@ -395,7 +396,7 @@ cell_augment (GtkRbTree *tree,
aug->col_end = right_aug->col_end;
if (right_aug->col_start != 0)
- aug->height -= cell->height;
+ aug->height -= cell->section_height + cell->height;
}
else
{
@@ -424,7 +425,7 @@ get_cell_at (GtkGridView *self,
if (tmp)
{
CellAugment *aug = gtk_list_item_manager_get_item_augment (self->item_manager, tmp);
- if (y < aug->height - cell->height ||
+ if (y < aug->height - cell_height (self, cell) ||
(y < aug->height && col < aug->col_end))
{
cell = tmp;
@@ -433,14 +434,14 @@ get_cell_at (GtkGridView *self,
if (cell->col_start == 0)
y -= aug->height;
else
- y -= aug->height - cell->height;
+ y -= aug->height - cell_height (self, cell);
pos += aug->parent.n_items;
}
- if (y < cell->height && col >= cell->col_start && col < cell->col_end)
+ if (y < cell_height (self, cell) && col >= cell->col_start && col < cell->col_end)
break;
if (cell->col_end == self->n_columns)
- y -= cell->height;
+ y -= cell_height (self, cell);
pos += cell->parent.n_items;
cell = gtk_rb_tree_node_get_right (cell);
@@ -480,14 +481,14 @@ gtk_grid_view_get_allocation_along (GtkListBase *base,
/* only multi-row cell, remaining items are irrelevant for other cells */
if (cell->cell_type == BLOCK)
{
- int row_height = cell_height (self, cell) / self->n_columns;
+ int row_height = cell->height / self->n_columns;
remaining /= self->n_columns;
if (offset)
- *offset = cell_y (self, cell) + remaining * row_height;
+ *offset = cell_y (self, cell) + remaining * row_height + (remaining ? cell->section_height : 0);
if (size)
- *size = row_height;
+ *size = row_height + (remaining ? 0 : cell->section_height);
}
else
{
@@ -569,26 +570,25 @@ gtk_grid_view_get_position_from_allocation (GtkListBase *base,
col = cell->col_start - 1;
break;
- case SECTION:
- cell = gtk_rb_tree_node_get_next (cell);
- while (cell->col_end < col)
- {
- cell = gtk_rb_tree_node_get_next (cell);
- pos += cell->parent.n_items;
- }
- break;
-
case BLOCK:
{
- int row_height = cell->height / (cell->parent.n_items / self->n_columns);
- int row = (y - y_offset) / row_height;
+ int row_height = (cell->height) / (cell->parent.n_items / self->n_columns);
+ int row = (y - y_offset < cell->section_height) ? 0 : (y - y_offset - cell->section_height) /
row_height;
*position = pos + row * self->n_columns + col;
if (area)
{
area->x = column_x (self, col);
area->width = column_x (self, col + 1) - area->x;
- area->y = y_offset + row * row_height;
- area->height = row_height;
+ if (row == 0)
+ {
+ area->y = y_offset;
+ area->height = row_height + cell->section_height;
+ }
+ else
+ {
+ area->y = y_offset + cell->section_height + row * row_height;
+ area->height = row_height;
+ }
}
return TRUE;
}
@@ -877,15 +877,18 @@ gtk_grid_view_measure (GtkWidget *widget,
static void
cell_set_size (Cell *cell,
+ int section_height,
int height,
int col_start,
int col_end)
{
- if (cell->height == height &&
+ if (cell->section_height == section_height &&
+ cell->height == height &&
cell->col_start == col_start &&
cell->col_end == col_end)
return;
+ cell->section_height = section_height;
cell->height = height;
cell->col_start = col_start;
cell->col_end = col_end;
@@ -901,7 +904,7 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
GtkGridView *self = GTK_GRID_VIEW (widget);
Cell *cell, *tmp;
GArray *heights;
- int min_row_height, row_height, total_height, total_width, col_min, col_nat, sec_min, sec_nat;
+ int min_row_height, row_height, section_height, total_height, total_width, col_min, col_nat, sec_min,
sec_nat;
GtkOrientation orientation, opposite_orientation;
GtkScrollablePolicy scroll_policy;
int x, y;
@@ -940,17 +943,13 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
cell != NULL;
cell = gtk_rb_tree_node_get_next (cell))
{
- if (cell->parent.section_header)
+ if (cell->parent.section_header && i > 0)
{
- if (i > 0)
- {
- cell->cell_type = FILLER;
- cell = gtk_list_item_manager_split_item (self->item_manager, cell, 0);
- i = 0;
- }
- cell->cell_type = SECTION;
+ cell->cell_type = FILLER;
cell = gtk_list_item_manager_split_item (self->item_manager, cell, 0);
+ i = 0;
}
+
if (cell->parent.n_items + i > self->n_columns)
{
if (i > 0)
@@ -1028,15 +1027,31 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
}
if (row_height > 0)
{
+ int min, nat;
total_height += row_height;
+ if (tmp->parent.section_header)
+ {
+ gtk_widget_measure (tmp->parent.section_header,
+ gtk_list_base_get_orientation (GTK_LIST_BASE (self)),
+ total_width,
+ &min, &nat, NULL, NULL);
+ if (scroll_policy == GTK_SCROLL_MINIMUM)
+ section_height = min;
+ else
+ section_height = nat;
+ total_height += section_height;
+ }
+ else
+ section_height = 0;
+
for (i = 0;
tmp != cell;
tmp = gtk_rb_tree_node_get_next (tmp))
{
if (tmp->cell_type == FILLER)
- cell_set_size (tmp, row_height, i, self->n_columns);
+ cell_set_size (tmp, section_height, row_height, i, self->n_columns);
else
- cell_set_size (tmp, row_height, i, i + tmp->parent.n_items);
+ cell_set_size (tmp, section_height, row_height, i, i + tmp->parent.n_items);
i += tmp->parent.n_items;
}
}
@@ -1046,24 +1061,6 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
cell = gtk_rb_tree_node_get_next (cell);
break;
- case SECTION:
- {
- int min, nat;
- tmp = gtk_rb_tree_node_get_next (cell);
- gtk_widget_measure (tmp->parent.section_header,
- gtk_list_base_get_orientation (GTK_LIST_BASE (self)),
- total_width,
- &min, &nat, NULL, NULL);
- if (scroll_policy == GTK_SCROLL_MINIMUM)
- row_height = min;
- else
- row_height = nat;
- total_height += row_height;
- cell_set_size (cell, row_height, 0, self->n_columns);
- cell = tmp;
- }
- break;
-
case FILLER:
case UNKNOWN:
default:
@@ -1086,11 +1083,25 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
if (cell->parent.widget == NULL &&
tmp->cell_type == FILLER)
{
+ if (cell->parent.section_header)
+ {
+ int min, nat;
+ gtk_widget_measure (cell->parent.section_header,
+ gtk_list_base_get_orientation (GTK_LIST_BASE (self)),
+ total_width,
+ &min, &nat, NULL, NULL);
+ if (scroll_policy == GTK_SCROLL_MINIMUM)
+ section_height = min;
+ else
+ section_height = nat;
+ }
+ else
+ section_height = 0;
/* Special case where we don't have assigned a height,
* becuase it's the last row in a block with filler */
- cell_set_size (cell, row_height, 0, cell->parent.n_items);
- cell_set_size (tmp, row_height, cell->parent.n_items, self->n_columns);
- total_height += row_height;
+ cell_set_size (cell, section_height, row_height, 0, cell->parent.n_items);
+ cell_set_size (tmp, section_height, row_height, cell->parent.n_items, self->n_columns);
+ total_height += section_height + row_height;
cell = gtk_rb_tree_node_get_next (tmp);
}
else
@@ -1104,13 +1115,23 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
break;
case BLOCK:
+ if (cell->parent.section_header)
+ {
+ int min, nat;
+ gtk_widget_measure (cell->parent.section_header,
+ gtk_list_base_get_orientation (GTK_LIST_BASE (self)),
+ total_width,
+ &min, &nat, NULL, NULL);
+ if (scroll_policy == GTK_SCROLL_MINIMUM)
+ section_height = min;
+ else
+ section_height = nat;
+ }
+ else
+ section_height = 0;
i = cell->parent.n_items / self->n_columns;
- cell_set_size (cell, i * row_height, 0, self->n_columns);
- total_height += row_height * i;
- cell = gtk_rb_tree_node_get_next (cell);
- break;
-
- case SECTION:
+ cell_set_size (cell, section_height, i * row_height, 0, self->n_columns);
+ total_height += section_height + row_height * i;
cell = gtk_rb_tree_node_get_next (cell);
break;
@@ -1136,6 +1157,15 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
cell != NULL;
cell = gtk_rb_tree_node_get_next (cell))
{
+ if (cell->parent.section_header)
+ {
+ gtk_list_base_size_allocate_child (GTK_LIST_BASE (self),
+ cell->parent.section_header,
+ - x,
+ y,
+ total_width,
+ cell->section_height);
+ }
switch (cell->cell_type)
{
case CELL:
@@ -1144,28 +1174,17 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
gtk_list_base_size_allocate_child (GTK_LIST_BASE (self),
cell->parent.widget,
cell_x (self, cell) - x,
- y,
+ y + cell->section_height,
cell_width (self, cell),
- cell_height (self, cell));
+ cell->height);
}
if (cell->col_end == self->n_columns)
- y += cell->height;
- break;
-
- case SECTION:
- tmp = gtk_rb_tree_node_get_next (cell);
- gtk_list_base_size_allocate_child (GTK_LIST_BASE (self),
- tmp->parent.section_header,
- cell_x (self, cell) - x,
- y,
- cell_width (self, cell),
- cell_height (self, cell));
- y += cell->height;
+ y += cell_height (self, cell);
break;
case BLOCK:
case FILLER:
- y += cell->height;
+ y += cell_height (self, cell);
break;
case UNKNOWN:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]