From eb5a8fa1a09e1d6c2b4fe8cb8ddb331fda0b6f2f Mon Sep 17 00:00:00 2001 From: TwoClocks <5883156+TwoClocks@users.noreply.github.com> Date: Sat, 6 Nov 2021 18:32:46 -0700 Subject: [PATCH 1/2] cut at new layout logic for LinearLayout --- cursive-core/src/views/linear_layout.rs | 104 ++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/cursive-core/src/views/linear_layout.rs b/cursive-core/src/views/linear_layout.rs index d2300510..a132c8af 100644 --- a/cursive-core/src/views/linear_layout.rs +++ b/cursive-core/src/views/linear_layout.rs @@ -505,6 +505,7 @@ impl View for LinearLayout { } } + #[allow(unreachable_code)] fn required_size(&mut self, req: Vec2) -> Vec2 { // Did anything change since last time? if let Some(size) = self.get_cache(req) { @@ -528,6 +529,109 @@ impl View for LinearLayout { self.cache = Some(SizeCache::build(ideal, req)); return ideal; } + // we're gonna use this alot for a bit. + let o = self.orientation; + + // split the screen evenly... + let even_size = req.get( o ); + let even_size = even_size / self.children.len(); + + + // this would work better if we could get the constrained + // sizes from the children, but I can't figure out how to do that. + // so instead : + + // clip everyone to even size, or the desired size, + // which ever is smaller. + // do it in a new list, so we can look at ideal sizes later. + let even_min : Vec = ideal_sizes.iter().map(|i| { + let new_size = min(even_size, *(i.get( o ))); + let mut n = i.clone(); + *(n.get_mut( o )) = new_size; + n + }).collect(); + + + debug!("even_min {:?}",even_min); + + // we fit now for sure. Might have violated + // constrained mins, but only if the screen is + // req is so small, and there isn't enough room + // for constrained mins... can't do anything + // about that... so just squash. + + // but we might have extra room to give out if + // some children wanted less than even_size + let used_size = o.stack( even_min.iter().copied()); + let used_size = used_size.get( o ); + let extra_size = req.get( o ) - used_size; + + debug!("extra size {}",extra_size); + + // only do this if there is some to give away. + let good_fit = if extra_size > 0 { + + // get a count of how many want more than the event amount + let big_cnt = even_min.iter().zip( ideal_sizes.iter() ).filter(|(even,ideal)| { + ideal.get( o ) > even.get( o ) + }).count(); + + // could be no one wants the extra size? + // I don't think we should get here and + // have this be < 1. Just in case. + if big_cnt > 0 { + // just split the extra evenly, and hand it out. + // we should get fancy and use weights, or + // pro-rata based on constrained size.... + // but life is short. + let each = extra_size / big_cnt; + + // give it away... + let mut adj_even : Vec = even_min.iter().zip( ideal_sizes.iter() ).map(|(even,ideal)| { + let mut fin = even.clone(); + if ideal.get( o ) > fin.get( o ) { + *(fin.get_mut(o)) += each + } + fin + }).collect(); + + // rounding error? + let odd_bit = extra_size & big_cnt; + if odd_bit > 0 { + // give it to the largest (e.g. one of the clipped ones) + let bigest = adj_even.iter_mut().reduce(|a,b|{ + if a.get( o ) > b.get( o ) { + a + } else { + b + } + }).unwrap(); + *(bigest.get_mut( o )) += odd_bit; + } + + + adj_even + } else { + // don't think we shout get here.. but just to be safe. + even_min + } + } else { + // all the childern are huge. no one wants less than the max. + // so just do the even split. + even_min + }; + + debug!("good fit {:?}",good_fit); + // ok. all done. Just resize everyone. + self.children.iter_mut().zip(good_fit.iter() ).for_each(|(child, fit)| { + child.required_size = *fit; + }); + + let done = o.stack( good_fit.iter().copied() ); + + debug!("ret {:?}", done); + + return done; // Ok, so maybe it didn't. Budget cuts, everyone. // Let's pretend we have almost no space in this direction. From 96e01071dac70374f8b9767eade5bccc0cc34082 Mon Sep 17 00:00:00 2001 From: TwoClocks <5883156+TwoClocks@users.noreply.github.com> Date: Sun, 12 Dec 2021 20:45:23 -0800 Subject: [PATCH 2/2] rustfmt and remove unsigned subtraction --- cursive-core/src/views/linear_layout.rs | 91 +++++++++++++------------ 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/cursive-core/src/views/linear_layout.rs b/cursive-core/src/views/linear_layout.rs index a132c8af..889be8f9 100644 --- a/cursive-core/src/views/linear_layout.rs +++ b/cursive-core/src/views/linear_layout.rs @@ -529,13 +529,12 @@ impl View for LinearLayout { self.cache = Some(SizeCache::build(ideal, req)); return ideal; } - // we're gonna use this alot for a bit. + // we're gonna use this a lot for a bit. let o = self.orientation; // split the screen evenly... - let even_size = req.get( o ); - let even_size = even_size / self.children.len(); - + let available_size = req.get(o); + let even_size = available_size / self.children.len(); // this would work better if we could get the constrained // sizes from the children, but I can't figure out how to do that. @@ -544,15 +543,17 @@ impl View for LinearLayout { // clip everyone to even size, or the desired size, // which ever is smaller. // do it in a new list, so we can look at ideal sizes later. - let even_min : Vec = ideal_sizes.iter().map(|i| { - let new_size = min(even_size, *(i.get( o ))); - let mut n = i.clone(); - *(n.get_mut( o )) = new_size; - n - }).collect(); - + let even_min: Vec = ideal_sizes + .iter() + .map(|i| { + let new_size = min(even_size, *(i.get(o))); + let mut n = i.clone(); + *(n.get_mut(o)) = new_size; + n + }) + .collect(); - debug!("even_min {:?}",even_min); + debug!("even_min {:?}", even_min); // we fit now for sure. Might have violated // constrained mins, but only if the screen is @@ -562,19 +563,21 @@ impl View for LinearLayout { // but we might have extra room to give out if // some children wanted less than even_size - let used_size = o.stack( even_min.iter().copied()); - let used_size = used_size.get( o ); - let extra_size = req.get( o ) - used_size; + let used_size = o.stack(even_min.iter().copied()); + let used_size = used_size.get(o); - debug!("extra size {}",extra_size); + debug!("available size {} used size {}", available_size, used_size); // only do this if there is some to give away. - let good_fit = if extra_size > 0 { + let good_fit = if used_size < available_size { + // get a count of how many want more than the even amount + let big_cnt = even_min + .iter() + .zip(ideal_sizes.iter()) + .filter(|(even, ideal)| ideal.get(o) > even.get(o)) + .count(); - // get a count of how many want more than the event amount - let big_cnt = even_min.iter().zip( ideal_sizes.iter() ).filter(|(even,ideal)| { - ideal.get( o ) > even.get( o ) - }).count(); + let extra_size = available_size - used_size; // unsigned math ok because of if above. // could be no one wants the extra size? // I don't think we should get here and @@ -587,47 +590,49 @@ impl View for LinearLayout { let each = extra_size / big_cnt; // give it away... - let mut adj_even : Vec = even_min.iter().zip( ideal_sizes.iter() ).map(|(even,ideal)| { - let mut fin = even.clone(); - if ideal.get( o ) > fin.get( o ) { - *(fin.get_mut(o)) += each - } - fin - }).collect(); + let mut adj_even: Vec = even_min + .iter() + .zip(ideal_sizes.iter()) + .map(|(even, ideal)| { + let mut fin = even.clone(); + if ideal.get(o) > fin.get(o) { + *(fin.get_mut(o)) += each + } + fin + }) + .collect(); // rounding error? let odd_bit = extra_size & big_cnt; if odd_bit > 0 { // give it to the largest (e.g. one of the clipped ones) - let bigest = adj_even.iter_mut().reduce(|a,b|{ - if a.get( o ) > b.get( o ) { - a - } else { - b - } - }).unwrap(); - *(bigest.get_mut( o )) += odd_bit; + let bigest = adj_even + .iter_mut() + .reduce(|a, b| if a.get(o) > b.get(o) { a } else { b }) + .unwrap(); + *(bigest.get_mut(o)) += odd_bit; } - adj_even } else { // don't think we shout get here.. but just to be safe. even_min } } else { - // all the childern are huge. no one wants less than the max. + // all the children are huge. no one wants less than the max. // so just do the even split. even_min }; - debug!("good fit {:?}",good_fit); + debug!("good fit {:?}", good_fit); // ok. all done. Just resize everyone. - self.children.iter_mut().zip(good_fit.iter() ).for_each(|(child, fit)| { - child.required_size = *fit; - }); + self.children.iter_mut().zip(good_fit.iter()).for_each( + |(child, fit)| { + child.required_size = *fit; + }, + ); - let done = o.stack( good_fit.iter().copied() ); + let done = o.stack(good_fit.iter().copied()); debug!("ret {:?}", done);