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:
@@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::types::{ Length, Rect, WidgetId };
|
||||
use crate::render::Canvas;
|
||||
use super::Element;
|
||||
use super::{ elide, Element };
|
||||
|
||||
mod theme;
|
||||
|
||||
@@ -357,35 +357,6 @@ impl<Msg: Clone> ListItem<Msg>
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorten `text` with a trailing ellipsis so it fits `max_w`, mirroring the
|
||||
/// single-line truncation [`super::text::Text`] applies.
|
||||
fn elide( canvas: &Canvas, text: &str, size: f32, max_w: f32 ) -> String
|
||||
{
|
||||
if max_w <= 0.0
|
||||
{
|
||||
return String::new();
|
||||
}
|
||||
if canvas.measure_text( text, size ) <= max_w
|
||||
{
|
||||
return text.to_string();
|
||||
}
|
||||
|
||||
let ellipsis = "...";
|
||||
let budget = max_w - canvas.measure_text( ellipsis, size );
|
||||
if budget <= 0.0
|
||||
{
|
||||
return ellipsis.to_string();
|
||||
}
|
||||
|
||||
let mut accum = 0.0_f32;
|
||||
let kept: String = text.chars().take_while( |ch|
|
||||
{
|
||||
accum += canvas.measure_text( &ch.to_string(), size );
|
||||
accum <= budget
|
||||
} ).collect();
|
||||
format!( "{kept}{ellipsis}" )
|
||||
}
|
||||
|
||||
/// Create a [`ListItem`] with the given primary label.
|
||||
///
|
||||
/// Add detail and behaviour through the chained builders. For a
|
||||
|
||||
Reference in New Issue
Block a user