From c72f19788022a996c2454d0aa5128f62ea976e11 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Fri, 21 Aug 2026 21:00:49 +0200 Subject: [PATCH] Stop a row of buttons deciding how wide the grid is MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **A Slint layout cannot be narrower than its children's minimums.** Given less room than they need it lays them out at those minimums, lets the row run past the edge — and reports the oversized minimum upwards. That second half is what made this more than cosmetic. The header, the filter chips and the grid are siblings in one VerticalLayout, so the widest row's minimum became the whole view's minimum: `LibraryGrid` was laid out wider than the window. The grid then measured itself against that inflated box and sized its columns to fill space that was off the screen, so the right-hand column was cut by the edge no matter what the tiling arithmetic did. Fourteen filter chips do not fit across 768 logical pixels, so that was every tablet in portrait. It also explains why opening the collections sidebar did not reflow the grid. The view was already pinned at a minimum wider than the window, so taking 232px away for the sidebar could not shrink it — it just clipped more of it. Each of those rows is now a horizontal Flickable. A Flickable's own minimum is nothing, since it exists to be smaller than what it holds, so none of them can inflate anything — and the controls past the edge became reachable instead of merely absent. Applied to all four: the library header, the filter chips, the compact action row disclosed by "More", and the develop strip. --- ui/dr-ui/ui/app.slint | 17 +++++++++- ui/dr-ui/ui/library.slint | 71 +++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/ui/dr-ui/ui/app.slint b/ui/dr-ui/ui/app.slint index 2fd86ec..68771f5 100644 --- a/ui/dr-ui/ui/app.slint +++ b/ui/dr-ui/ui/app.slint @@ -64,7 +64,21 @@ component StatusBar inherits Rectangle { height: 44px; background: Theme.surface; - HorizontalLayout { + // Scrolls rather than overflowing. A layout given less width than its + // children need does not shrink them — it overruns the edge and reports + // the oversized minimum to whatever contains it. Collapsing the + // instrumentation below buys back about 200 logical pixels, which is + // enough for a tablet; it is not enough for a phone, and nothing here + // should be unreachable merely because the window is narrow. + Flickable { + width: 100%; + height: 100%; + viewport-height: self.height; + viewport-width: max(self.width, strip.preferred-width); + + strip := HorizontalLayout { + width: parent.viewport-width; + height: parent.viewport-height; padding-left: Theme.gap; padding-right: Theme.gap; spacing: Theme.gap; @@ -204,6 +218,7 @@ component StatusBar inherits Rectangle { } } + } Rectangle { y: parent.height - 1px; diff --git a/ui/dr-ui/ui/library.slint b/ui/dr-ui/ui/library.slint index 2388030..a17f4fa 100644 --- a/ui/dr-ui/ui/library.slint +++ b/ui/dr-ui/ui/library.slint @@ -1012,7 +1012,23 @@ export component LibraryGrid inherits Rectangle { height: 44px; background: Theme.surface; - HorizontalLayout { + // Scrolls rather than overflowing, for the reason set out on the + // filter row below: a layout given less width than its children + // need does not shrink them, it overruns *and* reports the + // oversized minimum upwards — which is how a header of buttons + // ended up dictating how many columns of thumbnails the grid + // thought it could draw. Seven action buttons and four readouts do + // not fit across a tablet even in landscape, which is why the last + // one was clipped by the screen edge. + Flickable { + width: 100%; + height: 100%; + viewport-height: self.height; + viewport-width: max(self.width, header-row.preferred-width); + + header-row := HorizontalLayout { + width: parent.viewport-width; + height: parent.viewport-height; padding-left: Theme.gap; padding-right: Theme.gap; spacing: Theme.gap; @@ -1124,6 +1140,7 @@ export component LibraryGrid inherits Rectangle { clicked => { root.actions-open = !root.actions-open; } } } + } } // The compact action row, disclosed by "More" above. @@ -1137,7 +1154,18 @@ export component LibraryGrid inherits Rectangle { height: 44px; background: Theme.surface; - HorizontalLayout { + // Scrolls, like the two rows above it. This is the row that exists + // *because* the header did not fit, so it is the last place to + // assume six buttons will. + Flickable { + width: 100%; + height: 100%; + viewport-height: self.height; + viewport-width: max(self.width, actions-row.preferred-width); + + actions-row := HorizontalLayout { + width: parent.viewport-width; + height: parent.viewport-height; padding-left: Theme.gap; padding-right: Theme.gap; alignment: start; @@ -1175,6 +1203,7 @@ export component LibraryGrid inherits Rectangle { open-settings => { root.open-settings(); } } } + } Rectangle { y: parent.height - 1px; @@ -1192,11 +1221,38 @@ export component LibraryGrid inherits Rectangle { height: 34px; background: Theme.surface; - HorizontalLayout { - padding-left: Theme.gap; - padding-right: Theme.gap; - spacing: 4px; - alignment: start; + // --- the chips scroll rather than overflowing -------------- + // + // **A layout cannot be narrower than its children's minimums.** + // Given less room than they need, Slint lays them out at their + // minimums and lets the row run past the edge — and, worse, the + // row reports that oversized minimum upwards. This row is a + // sibling of the grid inside one VerticalLayout, so its minimum + // became the *whole view's* minimum: `LibraryGrid` was laid out + // wider than the window, the grid measured itself against that + // inflated box, and the right-hand column was computed to fit in + // space that was off the screen. Fourteen chips do not fit across + // 768 logical pixels, so that is every tablet in portrait. + // + // A Flickable's own minimum is nothing — it is built to be smaller + // than what it holds — so wrapping the row both stops it inflating + // anything and makes the chips past the edge reachable instead of + // merely absent. + Flickable { + width: 100%; + height: 100%; + // Horizontal only: there is one row of chips and it must not + // drift vertically inside a 34px strip. + viewport-height: self.height; + viewport-width: max(self.width, chips.preferred-width); + + chips := HorizontalLayout { + width: parent.viewport-width; + height: parent.viewport-height; + padding-left: Theme.gap; + padding-right: Theme.gap; + spacing: 4px; + alignment: start; Caption { text: "Show"; @@ -1310,6 +1366,7 @@ export component LibraryGrid inherits Rectangle { emphasised: true; vertical-alignment: center; } + } } Rectangle {