Gridview fix rubberbanding issues
Closes#3462 and #3445
See merge request GNOME/gtk!4688
(cherry picked from commit 0c052c9a37)
2bcae546 gridview: Move gtk_grid_view_computer_total_height() up for reuse
c6f357e4 gridview: Limit rectangle to gridview columns
1e9a36ff gridview: Allow starting rubberband in empty space below last row
ba909cf9 gridview: Fix get_items_in_rect() selection
f3fc8f5b gridview: Return an empty bitset when selecting only empty space
57c032e6 listbase: Clear selection if rubberband selected an empty set
aba2d994 gridview: Fix typo in docstring for gtk_grid_view_get_cell_at_y()
e14b84ff listview: Return an empty bitset when selecting only empty space
d6fab140 listview: Allow starting rubberband in empty space below last row
a7bbc258 listview: Fix selection for last item in get_items_in_rect
Remove a boatload of "or %NULL" from nullable parameters
and return values. gi-docgen generates suitable text from
the annotation that we don't need to duplicate.
This adds a few missing nullable annotations too.
Match GtkListBox, so it's possible to use the same styles for them.
Update GtkListView and GtkGridView docs to reflect that, fix a few gtk-doc
formatting leftovers along the way.
Use the TREE_GRID, ROW, COLUMN_HEADER and GRID_CELL roles
for the various widgets involved in a GtkColumnView. To
enable this, we subclass GtkListView for the internal
list in the column view.
Removed sentence that claimed the view will wrap the model in a
GtkSingleSelection, as it's no longer true. Fixed the code example in
GtkListView for the same reason. Fixed a small typo in GtkDropDown docs.
Now that both arguments to the _new_with_factory() constructors
are nullable, there's no good reason to keep a separate _new()
around. Just make gtk_list_view_new() and gtk_grid_view_new()
take both a model and a factory.
Change the apis in GtkListView, GtkColumnView and
GtkGridView to be explicitly about GtkSelectionModel,
to make it obvious that the widgets handle selection.
Update all users.
Make both gtk_list_view_new and gtk_list_view_new_with_factory
take a model as first argument, and make all arguments
allow-none and transfer full.
Update all callers.
Instead of storing the active items as we go, compute the affected items
whenever the rubberband changes and in particular when the rubberband
ends.
That way, the rubberband is guaranteed to select a rectangle even
after scrolling very far.
This is achieved by having a get_items_in_rect() vfunc that selects all
the items in the rubberbanded rectangle and returns them as a bitset.
The new names are
GtkListView - listview row
GtkGridView - gridview child
GtkColumView - columnview header
columnview listview row
Adwaita css has been updated to preserve
existing styles.
Fixes: #2818
Nothing really changes, because both ListView and GridView still keep
self->item_manager around, but it's set up to point at the base's item
manager.
This way we can slowly move things to GtkListBase that need the item
manager (like trackers).
- Handle anchor as align + top/bottom
This fixes behavior for cells that are higher than the view
- Add gtk_list_view_adjustment_is_flipped()
This should fix RTL handling of horizontal lists
- Fix scrolling
This should make scrolling more reliable, particularly on short lists
that are only a few pages long.
Due to the many different ways to set factories, it makes sense to
expose them as custom objects.
This makes the actual APIs for the list widgets simpler, because they
can just have a regular "factory" property.
As a convenience function, gtk_list_view_new_with_factory() was added
to make this whole approach easy to use from C.
Shift-clicking to extend selections now also works, imitating the
behavior of normal clicking and Windows Explorer (but not treeview):
1. We track the last selected item (normally, not via extend-clicking).
2. When shift-selecting, we modify the range from the last selected item
to this item the same way we modify the regular item when not using
shift:
2a. If Ctrl is not pressed, we select the range and unselect everything
else.
2b. If Ctrl is pressed, we make the range have the same selection state
as the last selected item:
- If the last selected item is selected, select the range.
- If the last selected item is not selected, unselect the range.