row, button, widget: distribute a row's width shortfall instead of overflowing, elide button labels into the rect they are granted, icon_size takes a Length
Row deficit distribution (layout/row.rs). `Row` knew how to hand out leftover width but had no notion of a shortfall: `leftover` was floored at zero and every child was laid out at its preferred width, so a cluster wider than its rect simply overflowed — and symmetrically, because the no-spacer branch centres the block, which is why both end labels of a segmented control were clipped at once rather than only the trailing one. The shortfall now comes off the widest children first, by water filling: `width_cap` sorts the flexible widths and returns the largest per-child cap `c` for which `sum( min( w, c ) ) <= available`, so a long title absorbs the whole deficit while an icon button beside it keeps its size, and equal siblings — a segmented control — share it evenly. A uniform scale-down, which was the first attempt, was wrong precisely there: it thinned a header's back arrow along with the title it sat next to. Spacers and flex children stay out of the flexible set, so a pinned gap keeps the width it was given — an explicit spacer is a decision, not slack — and `Row::no_shrink()` opts a row out entirely, for strips deliberately wider than their viewport such as a carousel rail meant to be scrolled. `align_right` and the centring branch now measure the laid width rather than the preferred one, so a shrunken row is positioned against what it actually occupies. Button label elision (widget/button/mod.rs, widget/mod.rs, widget/list_item/mod.rs). Shrinking a row is only half the fix: a leaf handed less width than it asked for still painted its full string, so the deficit came out clipped instead of truncated. `draw_text_button` now elides the label against the rect the layout granted, less the horizontal padding, for all three variants. The truncation rule moves out of `ListItem`, where it was a private helper, into a single crate-internal `widget::elide` the two share. `Text` keeps its own inline copy for now: it measures through an optional font override that this signature does not carry, and folding the two together is a separate change. icon_size as a Length (widget/button/mod.rs). `Button::icon_size` was the one geometry setter that ignored the widget-scaling mode — it took a bare `f32`, pinned it, and used `0.0` as the "unset" sentinel. It now takes `impl Into<Length>` behind an `Option` and resolves through `Canvas::resolve_geom`, the way `height`, `width` and `font_size` already do. A bare number still means `Length::px`, so every existing call keeps its exact size; what it adds is `Length::widget( n )`, which follows the active mode the way stock icons do. Without it a back arrow pinned at 21 px sat next to a `list_item` chevron that fluid sizing had grown well past 21, and read as visibly smaller on the same row.
This commit is contained in:
@@ -32,6 +32,7 @@ All notable changes to `ltk` are documented here. The format is based on [Keep a
|
||||
|
||||
### Changed
|
||||
|
||||
- **`Button::icon_size` takes `impl Into<Length>`** and resolves through `Canvas::resolve_geom`, joining `font_size` / `height` / `width`. A bare `f32` still means `Length::px` — every existing call keeps its exact size — but a caller can now pass `Length::widget( n )` to have an icon button follow the widget-scaling mode the way stock icons do. Without it an explicit `icon_size` was the one geometry setter that ignored the mode, so a 21 px back arrow sat next to a `list_item` chevron that fluid sizing had grown well past 21 and looked visibly smaller.
|
||||
- **`Length::dp` now applies the density at resolution time, not at construction.** The value carries its design pixels in a new `LengthBase::Dp` variant and `resolve` multiplies by the density in effect when it runs, so a `set_density` change takes effect on the next paint without rebuilding the view's lengths — previously a `dp` value was frozen to the density read when it was constructed. Behaviour is unchanged for code that sets density once at startup.
|
||||
- **The GLES image texture cache is now bounded** to 32 MiB of estimated GPU memory with least-recently-drawn eviction (the in-use entry is never evicted). Previously it grew without limit for the canvas' lifetime, so a stream of distinct buffers (photo carousel, video thumbnails) could exhaust GPU memory.
|
||||
- **`OverlaySpec::size`** is now `( Length, Length )` (was `( u32, u32 )`), resolved against the main surface when the overlay is materialized; wrap existing sizes in `Length::px( … )` for the old fixed behaviour.
|
||||
@@ -42,6 +43,7 @@ All notable changes to `ltk` are documented here. The format is based on [Keep a
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Rows no longer spill their children out of the layout.** `Row` distributed leftover width but had no notion of a shortfall: `leftover` floored at zero, so a cluster wider than its rect kept every preferred width and overflowed — symmetrically, since the no-spacer branch centres it, which is why both end labels of a segmented control were clipped at once. The shortfall now comes off the widest children first (water filling), so a long title gives up its width while the icon beside it keeps its size, and equal siblings — a segmented control — share it evenly; pinned spacers keep their width, and `Row::no_shrink()` opts out for strips deliberately wider than their viewport. `Button` elides its label into the rect it is granted, so shrinking degrades to a truncated label rather than clipped glyphs; the truncation rule moves to one crate-internal helper shared with `ListItem`.
|
||||
- **`ListItem` labels no longer run under the trailing slot.** The label and subtitle were painted with no width limit, so a title longer than the row overlapped the trailing text or the disclosure icon instead of truncating. The trailing slots are now laid out first and both lines are elided with an ellipsis against the space they leave, matching what `Text` already did.
|
||||
- **Text inputs no longer insert mid-string when the value grows after focus.** Focusing a text input pinned the cursor to a snapshot of `value.len()`; if the value kept growing without the widget seeing keystrokes (a field fed over IPC), the first normally-delivered key inserted at the stale position. The focus-time cursor is now an end-of-value sentinel that every consumer clamps to the current value length, collapsing to a concrete position on the first real keystroke or click.
|
||||
- **Single-line caret height now follows the text line.** The caret spanned `rect.height - 16`, so a field taller than its text line grew an oversized caret; it now measures `font_size + 4` and is vertically centered like the text, matching the multiline caret.
|
||||
|
||||
Reference in New Issue
Block a user