From 757063694e340d85640a82123dfdfa7493376e4e Mon Sep 17 00:00:00 2001 From: "Pedro M. de Echanove Pasquin" Date: Wed, 20 May 2026 15:24:34 +0200 Subject: [PATCH] =?UTF-8?q?layout/stack:=20opt-in=20`Stack::fit=5Fcontent(?= =?UTF-8?q?)`=20so=20a=20wrapping=20container=20can=20adopt=20the=20stack'?= =?UTF-8?q?s=20intrinsic=20size=20`Stack::preferred=5Fsize`=20unconditiona?= =?UTF-8?q?lly=20reported=20`(max=5Fwidth,=20max=5Fh)`=20=E2=80=94=20every?= =?UTF-8?q?=20stack=20claimed=20the=20full=20width=20its=20parent=20offere?= =?UTF-8?q?d,=20regardless=20of=20what=20its=20children=20actually=20neede?= =?UTF-8?q?d.=20That=20is=20the=20right=20default=20for=20a=20FrameLayout-?= =?UTF-8?q?style=20overlay=20(the=20existing=20callers=20all=20rely=20on?= =?UTF-8?q?=20it)=20but=20it=20makes=20the=20natural=20"pin=20a=20stack=20?= =?UTF-8?q?to=20a=20fixed-size=20child=20(e.g.=20a=20spacer=20of=20`card?= =?UTF-8?q?=5Fw=20=C3=97=20card=5Fh`)=20and=20centre=20other=20children=20?= =?UTF-8?q?on=20top=20of=20it"=20pattern=20impossible:=20a=20container=20w?= =?UTF-8?q?rapping=20such=20a=20stack=20always=20inherited=20the=20full=20?= =?UTF-8?q?parent=20width=20and=20ignored=20the=20spacer's=20footprint.=20?= =?UTF-8?q?The=20new=20`Stack::fit=5Fcontent()`=20builder=20mirrors=20the?= =?UTF-8?q?=20`Column::fit=5Fcontent`=20flag=20=E2=80=94=20when=20set,=20`?= =?UTF-8?q?preferred=5Fsize`=20returns=20the=20max=20of=20children's=20int?= =?UTF-8?q?rinsic=20widths=20and=20heights=20instead=20of=20claiming=20the?= =?UTF-8?q?=20parent's=20`max=5Fwidth`,=20with=20the=20same=20"skip=20fill?= =?UTF-8?q?er=20widgets=20that=20themselves=20claim=20`max=5Fwidth`"=20exc?= =?UTF-8?q?lusion=20list=20(`Spacer`=20with=20no=20`fixed=5Fwidth`,=20`Sep?= =?UTF-8?q?arator`,=20`Scroll`,=20`ProgressBar`,=20`Slider`,=20`TextEdit`?= =?UTF-8?q?=20without=20`fixed=5Fwidth`)=20so=20the=20flag=20is=20not=20de?= =?UTF-8?q?feated=20by=20a=20flexible=20child=20slipping=20into=20the=20st?= =?UTF-8?q?ack.=20Default=20behaviour=20is=20unchanged.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/stack.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/layout/stack.rs b/src/layout/stack.rs index c275921..4565657 100644 --- a/src/layout/stack.rs +++ b/src/layout/stack.rs @@ -54,6 +54,7 @@ pub struct Stack /// Children with their alignment, margin, and extra `(x, y)` translation /// applied after alignment. Drawn in order — last child is on top. pub children: Vec<( Element, HAlign, VAlign, f32, f32, f32 )>, + pub fit_content: bool, } impl Stack @@ -61,7 +62,13 @@ impl Stack /// Create an empty stack. pub fn new() -> Self { - Self { children: Vec::new() } + Self { children: Vec::new(), fit_content: false } + } + + pub fn fit_content( mut self ) -> Self + { + self.fit_content = true; + self } /// Append a child that fills the entire Stack rect (Android FrameLayout default). @@ -111,9 +118,31 @@ impl Stack self } - /// Return the preferred `(width, height)` — the maximum height among children. pub fn preferred_size( &self, max_width: f32, canvas: &Canvas ) -> (f32, f32) { + if self.fit_content + { + let content_w = self.children.iter() + .map( |( c, _, _, _, _, _ )| match c + { + Element::Spacer( s ) => s.fixed_width.unwrap_or( 0.0 ), + Element::Separator( _ ) => 0.0, + Element::Scroll( _ ) => 0.0, + Element::ProgressBar( _ ) => 0.0, + Element::Slider( _ ) => 0.0, + Element::TextEdit( t ) => if t.fixed_width.is_some() + { + t.preferred_size( max_width, canvas ).0 + } else { 0.0 }, + other => other.preferred_size( max_width, canvas ).0, + } ) + .fold( 0.0_f32, f32::max ); + let max_h = self.children.iter() + .map( |( c, _, _, _, _, _ )| c.preferred_size( max_width, canvas ).1 ) + .fold( 0.0_f32, f32::max ); + return ( content_w.min( max_width ), max_h ); + } + let max_h = self.children.iter() .map( |( c, _, _, _, _, _ )| c.preferred_size( max_width, canvas ).1 ) .fold( 0.0_f32, f32::max ); @@ -163,6 +192,7 @@ impl Stack .map( |( child, ha, va, margin, ox, oy )| ( child.map_arc( f ), ha, va, margin, ox, oy ) ) .collect(), + fit_content: self.fit_content, } } }