toggle, widget: scale the pill with an explicit row height, and give elide a half-pixel tolerance
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled

Toggle::height used to adjust only the row: the resolved value was floored at the theme track height and the pill kept its theme size, so a toggle capped below the fluid row height still rendered a full-size pill — on large surfaces, visibly out of scale next to controls that honour their cap. The floor is gone; when the resolved height falls below the theme row height, track and thumb now scale down proportionally (never up — the factor is capped at 1), and preferred_size reports the scaled track width so layout, focus ring and centring stay consistent. A toggle without an explicit height is untouched.
elide compared measure( text ) <= max_w strictly, which breaks when the caller sized itself from the same measurement: a button reports text + 2×pad as its preferred width, the layout grants exactly that, and draw hands elide back rect.width − 2×pad. In f32 the add-then-subtract round-trip can land a few ULP under the original measurement, the strict comparison fails, and the truncation branch then costs the full width of the ellipsis — a sub-pixel deficit turned "Empezar" into "Empez...". The fit check now allows half a pixel of slack, which absorbs any mismatch of this class while leaving genuine overflows to truncate as before.
This commit is contained in:
2026-08-09 12:07:35 +02:00
parent 1290f9400e
commit 477ef13ff4
2 changed files with 19 additions and 13 deletions

View File

@@ -128,7 +128,10 @@ pub( crate ) fn elide(
{
return String::new();
}
if canvas.measure_text( text, size ) <= max_w
// Half-pixel slack: a parent that sized itself from this same
// measurement can hand back a width a few ULP short after its
// padding add-then-subtract round-trip.
if canvas.measure_text( text, size ) <= max_w + 0.5
{
return text.to_string();
}

View File

@@ -89,9 +89,10 @@ impl<Msg: Clone> Toggle<Msg>
/// Override the preferred height (default: the theme row height,
/// `theme::HEIGHT` design px). Accepts any [`Length`] so dense
/// layouts can tie the row height to the viewport. The resolved
/// value is floored at the track height so the pill never clips;
/// the track keeps its theme size and stays vertically centred.
/// layouts can tie the row height to the viewport. When the resolved
/// value falls below the theme row height, the pill (track and thumb)
/// scales down proportionally so it never clips; it never grows
/// beyond its theme size.
pub fn height( mut self, h: impl Into<Length> ) -> Self
{
self.height = Some( h.into() );
@@ -105,7 +106,13 @@ impl<Msg: Clone> Toggle<Msg>
/// label is set. Height is the theme-defined row height.
pub fn preferred_size( &self, max_width: f32, canvas: &Canvas ) -> (f32, f32)
{
let track_w = canvas.geom_px( theme::TRACK_W );
let h = match self.height
{
Some( l ) => canvas.resolve_geom( l ),
None => canvas.geom_px( theme::HEIGHT ),
};
let scale = ( h / canvas.geom_px( theme::HEIGHT ) ).min( 1.0 );
let track_w = canvas.geom_px( theme::TRACK_W ) * scale;
let w = if let Some( ref label ) = self.label
{
let text_w = canvas.measure_text( label, canvas.font_px( theme::FONT_SIZE ) );
@@ -113,11 +120,6 @@ impl<Msg: Clone> Toggle<Msg>
} else {
track_w.min( max_width )
};
let h = match self.height
{
Some( l ) => canvas.resolve_geom( l ).max( canvas.geom_px( theme::TRACK_H ) ),
None => canvas.geom_px( theme::HEIGHT ),
};
( w, h )
}
@@ -133,9 +135,10 @@ impl<Msg: Clone> Toggle<Msg>
pub fn draw( &self, canvas: &mut Canvas, rect: Rect, focused: bool )
{
let track_w = canvas.geom_px( theme::TRACK_W );
let track_h = canvas.geom_px( theme::TRACK_H );
let thumb_size = canvas.geom_px( theme::THUMB_SIZE );
let scale = ( rect.height / canvas.geom_px( theme::HEIGHT ) ).min( 1.0 );
let track_w = canvas.geom_px( theme::TRACK_W ) * scale;
let track_h = canvas.geom_px( theme::TRACK_H ) * scale;
let thumb_size = canvas.geom_px( theme::THUMB_SIZE ) * scale;
let track_x = if let Some( ref label ) = self.label
{