From 477ef13ff472b7e566f67e1fc52a5f35ec856457 Mon Sep 17 00:00:00 2001 From: "Pedro M. de Echanove Pasquin" Date: Sun, 9 Aug 2026 12:07:35 +0200 Subject: [PATCH] =?UTF-8?q?toggle,=20widget:=20scale=20the=20pill=20with?= =?UTF-8?q?=20an=20explicit=20row=20height,=20and=20give=20elide=20a=20hal?= =?UTF-8?q?f-pixel=20tolerance=20Toggle::height=20used=20to=20adjust=20onl?= =?UTF-8?q?y=20the=20row:=20the=20resolved=20value=20was=20floored=20at=20?= =?UTF-8?q?the=20theme=20track=20height=20and=20the=20pill=20kept=20its=20?= =?UTF-8?q?theme=20size,=20so=20a=20toggle=20capped=20below=20the=20fluid?= =?UTF-8?q?=20row=20height=20still=20rendered=20a=20full-size=20pill=20?= =?UTF-8?q?=E2=80=94=20on=20large=20surfaces,=20visibly=20out=20of=20scale?= =?UTF-8?q?=20next=20to=20controls=20that=20honour=20their=20cap.=20The=20?= =?UTF-8?q?floor=20is=20gone;=20when=20the=20resolved=20height=20falls=20b?= =?UTF-8?q?elow=20the=20theme=20row=20height,=20track=20and=20thumb=20now?= =?UTF-8?q?=20scale=20down=20proportionally=20(never=20up=20=E2=80=94=20th?= =?UTF-8?q?e=20factor=20is=20capped=20at=201),=20and=20preferred=5Fsize=20?= =?UTF-8?q?reports=20the=20scaled=20track=20width=20so=20layout,=20focus?= =?UTF-8?q?=20ring=20and=20centring=20stay=20consistent.=20A=20toggle=20wi?= =?UTF-8?q?thout=20an=20explicit=20height=20is=20untouched.=20elide=20comp?= =?UTF-8?q?ared=20measure(=20text=20)=20<=3D=20max=5Fw=20strictly,=20which?= =?UTF-8?q?=20breaks=20when=20the=20caller=20sized=20itself=20from=20the?= =?UTF-8?q?=20same=20measurement:=20a=20button=20reports=20text=20+=202?= =?UTF-8?q?=C3=97pad=20as=20its=20preferred=20width,=20the=20layout=20gran?= =?UTF-8?q?ts=20exactly=20that,=20and=20draw=20hands=20elide=20back=20rect?= =?UTF-8?q?.width=20=E2=88=92=202=C3=97pad.=20In=20f32=20the=20add-then-su?= =?UTF-8?q?btract=20round-trip=20can=20land=20a=20few=20ULP=20under=20the?= =?UTF-8?q?=20original=20measurement,=20the=20strict=20comparison=20fails,?= =?UTF-8?q?=20and=20the=20truncation=20branch=20then=20costs=20the=20full?= =?UTF-8?q?=20width=20of=20the=20ellipsis=20=E2=80=94=20a=20sub-pixel=20de?= =?UTF-8?q?ficit=20turned=20"Empezar"=20into=20"Empez...".=20The=20fit=20c?= =?UTF-8?q?heck=20now=20allows=20half=20a=20pixel=20of=20slack,=20which=20?= =?UTF-8?q?absorbs=20any=20mismatch=20of=20this=20class=20while=20leaving?= =?UTF-8?q?=20genuine=20overflows=20to=20truncate=20as=20before.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widget/mod.rs | 5 ++++- src/widget/toggle/mod.rs | 27 +++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/widget/mod.rs b/src/widget/mod.rs index b57e606..1717495 100755 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -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(); } diff --git a/src/widget/toggle/mod.rs b/src/widget/toggle/mod.rs index d69d3c0..965fc86 100644 --- a/src/widget/toggle/mod.rs +++ b/src/widget/toggle/mod.rs @@ -89,9 +89,10 @@ impl Toggle /// 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 ) -> Self { self.height = Some( h.into() ); @@ -105,7 +106,13 @@ impl Toggle /// 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 Toggle } 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 Toggle 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 {