Commit Graph

59766 Commits

Author SHA1 Message Date
Benjamin Otte
2ff9af0564 listview: Add gtk_list_view_get_position_at_y() 2019-12-12 07:47:44 +01:00
Benjamin Otte
6642692f98 listitem: Add "listitem.select" action and keybindings for it
In fact, grab space with all modifiers to toggle selection of the
current item.
2019-12-12 07:47:44 +01:00
Benjamin Otte
5d235a9afe listview: Add a focus tracker
This ensures that the row with the input focus always stays available,
even when scrolled out of view.
2019-12-12 07:47:44 +01:00
Benjamin Otte
6b8d46fb30 listview: Implement (un)select all
Adds listitem.select-all and listitem.unselect-all actions and installs
the same keybindings as the treeview for those actions.
2019-12-12 07:47:44 +01:00
Benjamin Otte
26e71e2d25 listview: Track focus movements and update selection
When focus moves via tab/arrow, we need to select the new item.
2019-12-12 07:47:44 +01:00
Benjamin Otte
250f95a018 listview: Implement activation
- a GtkListview::activate signal
- a GtkListItem::activatable property
- activate list items on double clicks and <Enter> presses
2019-12-12 07:47:44 +01:00
Benjamin Otte
10034f8614 treeexpander: Implement input support
This implements all the keybindings from GtkTreeView that can be
supported.

It does not implement expand-all, because supporting that means
causing the TreeListModel to emit lots of create_model vfuncs which in
turn would cause many items-changed signal which in turn would cause
many signal handlers to run which in turn would make "expand-all" very
reentrant, and I'm uneasy about supporting that.

For the mouse, just add a click gesture to the expander icon that toggles
expanded state.
2019-12-12 07:47:44 +01:00
Benjamin Otte
fc9b66537e listitem: Change focus handling
Focus in the listitem now works like this:
1. If any child can take focus, do not ever attempt
   to take focus.
2. Otherwise, if this item is selectable or activatable,
   allow focusing this widget.

This makes sure every item in a list is focusable for
activation and selection handling, but no useless widgets
get focused and moving focus is as fast as possible.
2019-12-12 07:47:44 +01:00
Benjamin Otte
61f9a81643 popover: Remove unneeded vfunc
The vfunc is identical to the GtkWidget implementation it replaces. So
just keep using that one.
2019-12-12 07:47:44 +01:00
Benjamin Otte
9b743bbf11 inspector: Make the recorder node list use a ListView
It's quite a bit faster now, but the code is also a bit more awkward.

Pain points:

- GtkTreeListModel cannot be created in UI files because it needs
  a CreateModelFunc.
  Using a signal for this doesn't work because autoexpand wants to
  expand the model before the signal handler is connected.

- The list item factory usage is still awkward. It's bearable here
  because the list items are very simple, but still.
2019-12-12 07:47:44 +01:00
Benjamin Otte
93757a9844 inspector: Use a GtkTreeExpander in the object tree 2019-12-12 07:47:44 +01:00
Benjamin Otte
dfd0dbd68f inspector: Use a treeexpander in the recorder 2019-12-12 07:47:44 +01:00
Benjamin Otte
f24785ae6e demo: Add a GSettings tree demo
It is meant to look somewhat like dconf-editor when it is done.

So far, it's just a list.
2019-12-12 07:47:44 +01:00
Benjamin Otte
84c175a82f Add GtkTreeExpander
This is a container widget that takes over all the duties of tree
expanding and collapsing.
It has to be a container so it can capture keybindings while focus is
inside the listitem.

So far, this widget does not allow interacting with it, but it shows the
expander arrow in its correct state.

Also, testlistview uses this widget now instead of implementing
expanding itself.
2019-12-12 07:47:44 +01:00
Benjamin Otte
5efbd2357d gridview: Actually do something
Implement measuring and allocating items - which makes the items appear
when drawing and allows interacting with the items.

However, the gridview still does not allow any user interaction
(including scrolling).
2019-12-12 07:47:44 +01:00
Benjamin Otte
458c235d91 listview: Pass the CSS name of listitems to the manager
... instead of hardcoding "row".
2019-12-12 07:47:44 +01:00
Benjamin Otte
1e23985d46 gridview: Implement GtkOrientable
Again, this is just the skeleton, because the Gridview does nothing yet.
2019-12-12 07:47:44 +01:00
Benjamin Otte
1b3a8b940d gridview: Add factory handling
Just copy the listview APIs.

Code still doesn't do anything with it.
2019-12-12 07:47:44 +01:00
Benjamin Otte
512eed7dde listview: Expose GtkListItemFactory APIs
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.
2019-12-12 07:47:44 +01:00
Benjamin Otte
0282a29c4d textview: Make cursor work when blinking is disabled 2019-12-12 07:47:44 +01:00
Benjamin Otte
ef2a426069 gtk-demo: Add a rough start at a Weather demo
This demos a horizontal listview.
2019-12-12 07:47:43 +01:00
Benjamin Otte
20287eb2fd listview: Implement GtkOrientable 2019-12-12 07:47:43 +01:00
Benjamin Otte
f72a09c2a5 tests: Add a rough form of multiselection
Just store a "filechooser::selected" attribute in the GFileInfo if
the file is meant to be selected.
2019-12-12 07:47:43 +01:00
Benjamin Otte
adc32f7643 listview: Implement extending selections
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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
2736cee578 listview: Add list.scroll_to_item action
The action scrolls the given item into view.

Listitems activate this action when they gain focus.
2019-12-12 07:47:43 +01:00
Benjamin Otte
42be3898e8 testlistview: Load icons async
Speeds up loading by 4x, because out of view icons aren't loaded
anymore.
2019-12-12 07:47:43 +01:00
Benjamin Otte
f3c6424086 testlistview: Port to directory list 2019-12-12 07:47:43 +01:00
Benjamin Otte
0a2c879911 listitemfactory: Add a factory for ui files
Reuse <template> magic to initialize GtkListItems. This feels
amazingly hacky, but it also amazingly worked on the first try.
2019-12-12 07:47:43 +01:00
Benjamin Otte
e85a3ff0a6 listitemfactory: Split implementation out
.. into gtkfunctionslistitemfactory.c

Now we can add a different implmenetation.
2019-12-12 07:47:43 +01:00
Benjamin Otte
231de097bf listitemfactory: vfuncify
No functional changes other than a new indirection.
2019-12-12 07:47:43 +01:00
Benjamin Otte
bfff265f81 listitemfactory: Sanitize APIs
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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
08a6ea1f99 listview: Add gtk_list_view_set_show_separators()
Do the same thing that GtkListBox does in commit
0249bd4f8a
2019-12-12 07:47:43 +01:00
Benjamin Otte
dc2f838d05 listitemmanager: Add trackers
... 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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
ed3b774ee1 listitemmanager: Simplify
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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
fe9f4e18fb gridview: Implement GtkScrollable
We can now scroll all the nothing we display.

We also clip it properly.
2019-12-12 07:47:43 +01:00
Benjamin Otte
e596631b42 listitemmanager: Move list of listitems here
All the listview infrastructure moved with it, so the next step is
moving that back...
2019-12-12 07:47:43 +01:00
Benjamin Otte
8c53d57eea wayland: Remove function declaration for nonexisting function 2019-12-12 07:47:43 +01:00
Benjamin Otte
fa6764e103 gridview: Add API for setting number of columns
The API isn't used yet.
2019-12-12 07:47:43 +01:00
Benjamin Otte
df111706ba gtk: Add a GtkGridView skeleton 2019-12-12 07:47:43 +01:00
Benjamin Otte
f05b5fbcb4 listitem: Add a press gesture to select the item
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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
4225ba314c listview: Add initial support for displaying selections 2019-12-12 07:47:43 +01:00
Benjamin Otte
34627af9e7 listview: Reset listitems' CSS animations when rebinding
This way, newly displayed rows don't play an unselect animation (text
fading in) when they are unselected, but the row was previously used for
a selected item.
2019-12-12 07:47:43 +01:00
Benjamin Otte
e0d3ed713e listview: Add selection properties to ListItem
This just brings the infrastructure into place, we're not using the
properties yet.
2019-12-12 07:47:43 +01:00
Benjamin Otte
57bfde6750 listview: Try to keep the list items in order when scrolling
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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
bdc7639dac listlistmodel: Add gtk_list_list_model_item_moved()
Use it to fix a case that just said g_warning ("oops").

Apparently I had forgotten the case where a container moved a child
in the widget tree.
2019-12-12 07:47:43 +01:00
Benjamin Otte
87e25f2d9a listitemmanager: Switch from "insert_before" to "insert_after" argumnet
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.
2019-12-12 07:47:43 +01:00
Benjamin Otte
698440ad8b testlistview: Create widgets only once
Previously, we were recreating all widgets every time the list item was
rebound, which caused a lot of extra work every time we scrolled.

Now we keep the widgets around and only set their properties again when
the item changes.
2019-12-12 07:47:43 +01:00
Benjamin Otte
62cc217199 testlistview: Show the row number
Always show the current row. This is mostly useful for debugging, not
for beauty.
2019-12-12 07:47:43 +01:00
Benjamin Otte
6bc7e6e6da listview: Only allocate necesary rows
This is the big one.

The listview only allocates 200 rows around the visible row now.
Everything else is kept in ListRow instances with row->widget == NULL.

For rows without a widget, we assign the median height of the child
widgets as the row's height and then do all calculations as if there
were widgets that had requested that height (like setting adjustment
values or reacting to adjustment value changes).

When the view is scrolled, we bind the 200 rows to the new visible area,
so that the part of the listview that can be seen is always allocated.
2019-12-12 07:47:43 +01:00
Benjamin Otte
418960dc72 listview: Change anchor handling again
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.
2019-12-12 07:47:43 +01:00