Tile the thumbnails to fill the width

The cells were drawn at whatever pixel size the class asked for and the
remainder was left as a bare strip down the right-hand side — up to one
short of a full column of nothing, which on a phone is a quarter of the
screen.

It also had the two quantities depending on each other the wrong way
round. The column count was derived from the fixed cell size, so the two
could disagree about how much room there was and the last column could
start inside the viewport and end outside it.

Solving for the cell removes both at once. Pick how many columns of
roughly the requested size fit — rounded, not floored, because the size
class is a request rather than a measurement and a width nine tenths of
the way to another column should take it — then make those columns share
the width. `columns` cells and the `columns + 1` gaps around them come to
exactly the grid's width, so there is no remainder to strand and nothing
can overhang.

The size class still decides what the user gets, since it is what the
column count is chosen from. It just no longer dictates the pixel, so the
cell flexes a few percent either way to make the row come out even.
This commit is contained in:
2026-08-21 20:44:48 +02:00
parent 90d6e551b3
commit 12a457b8d0
+31 -14
View File
@@ -952,23 +952,40 @@ export component LibraryGrid inherits Rectangle {
// the comments on `panel-visible` in app.slint warn about, and this is not
// an instance of it.
/// The drawn cell, never wider than the column it has to sit in.
/// How many columns of roughly the requested size the grid holds.
///
/// `columns` floors to a minimum of one, so a cell larger than the grid
/// still produced a single column — of a cell that did not fit, running
/// off the right-hand edge with no way to scroll to it. That is reachable
/// from the size classes alone on a tablet in portrait: 768 logical pixels
/// wide, less the timeline and any open sidebar, is narrower than the
/// larger classes assume.
/// **Rounded, not floored.** The size class is a request, not a
/// measurement — what the user is choosing is "about this big" — so a
/// width that is nine tenths of the way to another column should take it
/// rather than leave nearly a whole column of dead space at the edge.
///
/// Capping here rather than clamping the size class keeps the user's
/// choice intact — rotate to landscape, or close the sidebar, and the
/// thumbnails grow back to the size that was asked for.
property <length> cell-size:
min(root.requested-cell-size, max(64px, grid-area.width - 2 * Theme.gap));
/// A minimum of one, so a grid narrower than a single cell still draws
/// that cell rather than none.
property <int> columns:
max(1, floor((grid-area.width - Theme.gap) / (cell-size + Theme.gap)));
max(1, round((grid-area.width - Theme.gap)
/ (root.requested-cell-size + Theme.gap)));
/// The drawn cell: the width, divided exactly.
///
/// **The tiles fill the grid.** They used to be drawn at whatever the size
/// class asked for and the remainder left as a bare strip down the
/// right-hand side — up to one cell short of a full column of nothing,
/// which on a phone is a quarter of the screen. Worse, the column count
/// was derived from that same fixed size, so the two disagreed about how
/// much room there was and the last column could start inside the viewport
/// and end outside it.
///
/// Solving for the cell instead removes both faults at once: pick how many
/// columns to draw, then make them share the width. `columns` cells and
/// the `columns + 1` gaps around them come to exactly `grid-area.width`,
/// so there is no remainder to strand and nothing can overhang.
///
/// The size class still decides what the user gets — it is what `columns`
/// is chosen from — it just no longer dictates the pixel, so the cell
/// flexes by a few percent either way to make the row come out even.
property <length> cell-size:
max(64px,
(grid-area.width - Theme.gap * (root.columns + 1)) / root.columns);
// Reported out so Rust can place month headings: a heading belongs on a
// cell that begins a row, and only the grid knows how wide a row is.
changed columns => { root.columns-changed(root.columns); }