Replace a previous fix with a more correct one: Update the
selected state from the model instead of reusing the old state, the
model might have updated the selected state.
The selection model will only emit one of items-changed
or selection-changed, so when we handle an items-changed,
we must assume that selection state may have changed for
any of the newly added items.
This fixes lingering selection state in the visible range
if you change the sorting of the colors demo.
Fixes: #2827
Add a mode to GtkListItemWidget that activates on
single click and selects on hover. Make
GtkListItemManager set this on its items
when its own 'property' of the same name is set.
This splits GtkListItem into 2 parts:
1. GtkListItem
This is purely a GObject with public API for developers who want to
populate lists. There is no chance to cause conflict with GtkWidget
properties that the list implementation assumed control over and
defines a clear boundary.
2. GtkListItemWidget
The widget part of the listitem. This is not only fully in control of
the list machinery, the machinery can also use different widget
implementations for different list widgets like I inted to for
GtkColumnView.
Make sure the APIs follow a predictable path:
setup
bind
rebind/update (0-N times)
unbind
teardown
This is the first step towards providing multiple different factories.
... and replace the anchor tracking with a tracker.
Trackers track an item through the list across changes and ensure that
this item (and potentially siblings before/after it) are always backed
by a GtkListItem and that if the item gets removed a replacement gets
chosen.
This is now used for tracking the anchor but can also be used to add
trackers for the cursor later.
Remove a bunch of API from the headers that isn't used anymore and then
refactor code to not call it anymore.
In particular, get rid of GtkListItemManagerChange and replace it with a
GHashTable.
This is implemented by using actions, which are a neat trick to get to
allow the ListItem to call functions on the ListView without actually
needing to be aware of it.
Instead of just destroying all items and then recreating them (or even
hide()ing and then show()ing them again (or even even repositioning
them in the widget tree)), just try to reust them in the order they are.
This works surprisingly well when scrolling and most/all widgets
just moved.
We reorder widgets start to end, so when reusing a list item, we
correctly know the previous sibling for that list item, but not the
next sibling yet. We just know the widget it should ultimately be in
front of.
So we can do a more correct guess of the list item's place in the widget
tree if we think about where to place an item like this.
Actually using this change will come in the next commit.
The anchor is now a tuple of { listitem, align }.
Using the actual list item allows keeping the anchor across changes
in position (ie when lists get resorted) while still being able to fall
back to positions (list items store their position) when an item gets
removed.
The align value is in the range [0..1] and defines where in the visible
area to do the alignment.
0.0 means to align the top of the row with the top of the visible area,
1.0 aligns the bottom of the widget with the visible area and 0.5 keeps
the center of the widget at the center of the visible area.
It works conceptually the same as percentages in CSS background-position
(where the background area and the background image's size are matched
the same way) or CSS transform-origin.
Also refactor the whole list item management yet again.
Now, list item APIs doesn't have bind/unbind functions anymore, but only
property setters.
The item factory is the only one doing the binding.
As before, the item manager manages when items need to be bound.
Require that items created with the manager get destroyed via the
manager.
To that purpose, renamed create_list_item() to acquire_list_item() and
add a matching release_list_item() function.
This way, the manager can in the future keep track of all items and
cache information about them.
It's all stubs for now, but here's the basic ideas about what
this object is supposed to do:
(1) It's supposed to be handling all the child GtkWidgets that are
used by the listview, so that the listview can concern
itself with how many items it needs and where to put them.
(2) It's meant to do the caching of widgets that are not (currently)
used.
(3) It's meant to track items that remain in the model across
items-changed emissions and just change position.
(2) It's code that can be shared between listview and potential
other widgets like a GridView.
It's also free to assume that the number of items it's supposed to
manage doesn't grow too much, so it's free to use O(N) algorithms.