Skip to content

Commit

Permalink
Merge branch 'gridview' into 'main'
Browse files Browse the repository at this point in the history
Gridview fix rubberbanding issues

Closes #3462 and #3445

See merge request GNOME/gtk!4688
  • Loading branch information
Benjamin Otte committed Jul 26, 2022
2 parents 2916966 + a7bbc25 commit 0c052c9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 34 deletions.
38 changes: 21 additions & 17 deletions gtk/gtkgridview.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ cell_augment (GtkRbTree *tree,
* index of the returned row
* @offset: (out caller-allocates) (optional): stores the offset
* in pixels between y and top of cell.
* @offset: (out caller-allocates) (optional): stores the height
* @size: (out caller-allocates) (optional): stores the height
* of the cell
*
* Gets the Cell that occupies the leftmost position in the row at offset
Expand Down Expand Up @@ -413,6 +413,19 @@ gtk_grid_view_get_allocation_across (GtkListBase *base,
return TRUE;
}

static int
gtk_grid_view_compute_total_height (GtkGridView *self)
{
Cell *cell;
CellAugment *aug;

cell = gtk_list_item_manager_get_root (self->item_manager);
if (cell == NULL)
return 0;
aug = gtk_list_item_manager_get_item_augment (self->item_manager, cell);
return aug->size;
}

static gboolean
gtk_grid_view_get_position_from_allocation (GtkListBase *base,
int across,
Expand All @@ -428,6 +441,7 @@ gtk_grid_view_get_position_from_allocation (GtkListBase *base,
return FALSE;

n_items = gtk_list_base_get_n_items (base);
along = CLAMP (along, 0, gtk_grid_view_compute_total_height (self) - 1);
if (!gtk_grid_view_get_cell_at_y (self,
along,
&pos,
Expand Down Expand Up @@ -467,16 +481,19 @@ gtk_grid_view_get_items_in_rect (GtkListBase *base,

result = gtk_bitset_new_empty ();

if (rect->y >= gtk_grid_view_compute_total_height (self))
return result;

n_items = gtk_list_base_get_n_items (base);
if (n_items == 0)
return result;

first_column = floor (rect->x / self->column_width);
last_column = floor ((rect->x + rect->width) / self->column_width);
first_column = fmax (floor (rect->x / self->column_width), 0);
last_column = fmin (floor ((rect->x + rect->width) / self->column_width), self->n_columns - 1);
if (!gtk_grid_view_get_cell_at_y (self, rect->y, &first_row, NULL, NULL))
first_row = rect->y < 0 ? 0 : n_items - 1;
if (!gtk_grid_view_get_cell_at_y (self, rect->y + rect->height, &last_row, NULL, NULL))
last_row = rect->y < 0 ? 0 : n_items - 1;
last_row = rect->y + rect->height < 0 ? 0 : n_items - 1;

gtk_bitset_add_rectangle (result,
first_row + first_column,
Expand Down Expand Up @@ -722,19 +739,6 @@ cell_set_size (Cell *cell,
gtk_rb_tree_node_mark_dirty (cell);
}

static int
gtk_grid_view_compute_total_height (GtkGridView *self)
{
Cell *cell;
CellAugment *aug;

cell = gtk_list_item_manager_get_root (self->item_manager);
if (cell == NULL)
return 0;
aug = gtk_list_item_manager_get_item_augment (self->item_manager, cell);
return aug->size;
}

static void
gtk_grid_view_size_allocate (GtkWidget *widget,
int width,
Expand Down
35 changes: 19 additions & 16 deletions gtk/gtklistbase.c
Original file line number Diff line number Diff line change
Expand Up @@ -1583,25 +1583,28 @@ gtk_list_base_stop_rubberband (GtkListBase *self,
return;

rubberband_selection = gtk_list_base_get_items_in_rect (self, &rect);
if (gtk_bitset_is_empty (rubberband_selection))
{
gtk_bitset_unref (rubberband_selection);
return;
}

if (modify && extend) /* Ctrl + Shift */
{
GtkBitset *current;
guint min = gtk_bitset_get_minimum (rubberband_selection);
guint max = gtk_bitset_get_maximum (rubberband_selection);
/* toggle the rubberband, keep the rest */
current = gtk_selection_model_get_selection_in_range (model, min, max - min + 1);
selected = gtk_bitset_copy (current);
gtk_bitset_unref (current);
gtk_bitset_intersect (selected, rubberband_selection);
gtk_bitset_difference (selected, rubberband_selection);

mask = gtk_bitset_ref (rubberband_selection);
if (gtk_bitset_is_empty (rubberband_selection))
{
selected = gtk_bitset_ref (rubberband_selection);
mask = gtk_bitset_ref (rubberband_selection);
}
else
{
GtkBitset *current;
guint min = gtk_bitset_get_minimum (rubberband_selection);
guint max = gtk_bitset_get_maximum (rubberband_selection);
/* toggle the rubberband, keep the rest */
current = gtk_selection_model_get_selection_in_range (model, min, max - min + 1);
selected = gtk_bitset_copy (current);
gtk_bitset_unref (current);
gtk_bitset_intersect (selected, rubberband_selection);
gtk_bitset_difference (selected, rubberband_selection);

mask = gtk_bitset_ref (rubberband_selection);
}
}
else if (modify) /* Ctrl */
{
Expand Down
7 changes: 6 additions & 1 deletion gtk/gtklistview.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ gtk_list_view_get_items_in_rect (GtkListBase *base,

result = gtk_bitset_new_empty ();

if (rect->y >= gtk_list_view_get_list_height (self))
return result;

n_items = gtk_list_base_get_n_items (base);
if (n_items == 0)
return result;
Expand All @@ -390,7 +393,7 @@ gtk_list_view_get_items_in_rect (GtkListBase *base,
if (row)
last = gtk_list_item_manager_get_item_position (self->item_manager, row);
else
last = rect->y < 0 ? 0 : n_items - 1;
last = rect->y + rect->height < 0 ? 0 : n_items - 1;

gtk_bitset_add_range_closed (result, first, last);
return result;
Expand Down Expand Up @@ -425,6 +428,8 @@ gtk_list_view_get_position_from_allocation (GtkListBase *base,
if (across >= self->list_width)
return FALSE;

along = CLAMP (along, 0, gtk_list_view_get_list_height (self) - 1);

row = gtk_list_view_get_row_at_y (self, along, &remaining);
if (row == NULL)
return FALSE;
Expand Down

0 comments on commit 0c052c9

Please sign in to comment.