From 3879e4293e92f2d7ffe4021ea44062a98b8700c4 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Tue, 8 Oct 2024 14:50:59 +0200 Subject: [PATCH] TMP --- masonry/src/box_constraints.rs | 111 ++++-------------- masonry/src/widget/align.rs | 2 +- masonry/src/widget/button.rs | 2 +- masonry/src/widget/flex.rs | 31 ++--- masonry/src/widget/grid.rs | 2 +- masonry/src/widget/image.rs | 2 +- masonry/src/widget/portal.rs | 3 +- masonry/src/widget/sized_box.rs | 34 ++---- masonry/src/widget/split.rs | 20 +--- ...ts__lifecycle_basic__app_creation.snap.new | 18 +++ 10 files changed, 69 insertions(+), 156 deletions(-) create mode 100644 masonry/src/widget/tests/snapshots/masonry__widget__tests__lifecycle_basic__app_creation.snap.new diff --git a/masonry/src/box_constraints.rs b/masonry/src/box_constraints.rs index fd96d0fe1..114510d69 100644 --- a/masonry/src/box_constraints.rs +++ b/masonry/src/box_constraints.rs @@ -8,9 +8,10 @@ use vello::kurbo::Size; /// The layout strategy for Masonry is strongly inspired by Flutter, /// and this struct is similar to the [Flutter BoxConstraints] class. /// -/// At the moment, it represents simply a minimum and maximum size. +/// At the moment, it represents only a maximum size. /// A widget's [`layout`] method should choose an appropriate size that -/// meets these constraints. +/// meets that constraint. +/// The algorithm is supposed to use a minimum constraint, but we're phasing that out. /// /// Further, a container widget should compute appropriate constraints /// for each of its child widgets, and pass those down when recursing. @@ -23,7 +24,6 @@ use vello::kurbo::Size; /// [rounded away from zero]: Size::expand #[derive(Clone, Copy, Debug, PartialEq)] pub struct BoxConstraints { - min: Size, max: Size, } @@ -32,7 +32,6 @@ impl BoxConstraints { /// /// Can be satisfied by any nonnegative size. pub const UNBOUNDED: BoxConstraints = BoxConstraints { - min: Size::ZERO, max: Size::new(f64::INFINITY, f64::INFINITY), }; @@ -44,37 +43,8 @@ impl BoxConstraints { /// so that the layout is aligned to integers. /// /// [rounded away from zero]: Size::expand - pub fn new(min: Size, max: Size) -> BoxConstraints { - BoxConstraints { - min: min.expand(), - max: max.expand(), - } - } - - /// Create a "tight" box constraints object. - /// - /// A "tight" constraint can only be satisfied by a single size. - /// - /// The given size is also [rounded away from zero], - /// so that the layout is aligned to integers. - /// - /// [rounded away from zero]: Size::expand - pub fn tight(size: Size) -> BoxConstraints { - let size = size.expand(); - BoxConstraints { - min: size, - max: size, - } - } - - /// Create a "loose" version of the constraints. - /// - /// Make a version with zero minimum size, but the same maximum size. - pub fn loosen(&self) -> BoxConstraints { - BoxConstraints { - min: Size::ZERO, - max: self.max, - } + pub fn new(max: Size) -> BoxConstraints { + BoxConstraints { max: max.expand() } } /// Clamp a given size so that it fits within the constraints. @@ -84,7 +54,7 @@ impl BoxConstraints { /// /// [rounded away from zero]: Size::expand pub fn constrain(&self, size: impl Into) -> Size { - size.into().expand().clamp(self.min, self.max) + size.into().expand().clamp(Size::ZERO, self.max) } /// Returns the max size of these constraints. @@ -92,11 +62,6 @@ impl BoxConstraints { self.max } - /// Returns the min size of these constraints. - pub fn min(&self) -> Size { - self.min - } - /// Whether there is an upper bound on the width. pub fn is_width_bounded(&self) -> bool { self.max.width.is_finite() @@ -115,12 +80,6 @@ impl BoxConstraints { return; } - if self.min.width.is_nan() { - debug_panic!("Minimum width constraint passed to {name} is NaN"); - } - if self.min.height.is_nan() { - debug_panic!("Minimum height constraint passed to {name} is NaN"); - } if self.max.width.is_nan() { debug_panic!("Maximum width constraint passed to {name} is NaN"); } @@ -128,25 +87,12 @@ impl BoxConstraints { debug_panic!("Maximum height constraint passed to {name} is NaN"); } - if self.min.width.is_infinite() { - debug_panic!("Infinite minimum width constraint passed to {name}"); - } - if self.min.height.is_infinite() { - debug_panic!("Infinite minimum height constraint passed to {name}"); - } - - if !(0.0 <= self.min.width - && self.min.width <= self.max.width - && 0.0 <= self.min.height - && self.min.height <= self.max.height - && self.min.expand() == self.min - && self.max.expand() == self.max) - { + if !(0.0 <= self.max.width && 0.0 <= self.max.height && self.max.expand() == self.max) { debug_panic!("Bad BoxConstraints passed to {name}: {self:?}",); } } - /// Shrink min and max constraints by size + /// Shrink max constraint by size /// /// The given size is also [rounded away from zero], /// so that the layout is aligned to integers. @@ -154,23 +100,18 @@ impl BoxConstraints { /// [rounded away from zero]: Size::expand pub fn shrink(&self, diff: impl Into) -> BoxConstraints { let diff = diff.into().expand(); - let min = Size::new( - (self.min().width - diff.width).max(0.), - (self.min().height - diff.height).max(0.), - ); let max = Size::new( (self.max().width - diff.width).max(0.), (self.max().height - diff.height).max(0.), ); - BoxConstraints::new(min, max) + BoxConstraints::new(max) } /// Test whether these constraints contain the given `Size`. pub fn contains(&self, size: impl Into) -> bool { let size = size.into(); - (self.min.width <= size.width && size.width <= self.max.width) - && (self.min.height <= size.height && size.height <= self.max.height) + (size.width <= self.max.width) && (size.height <= self.max.height) } /// Find the `Size` within these `BoxConstraint`s that minimises the difference between the @@ -203,9 +144,9 @@ impl BoxConstraints { // Then we check if any `Size`s with our desired aspect ratio are inside the constraints. // TODO this currently outputs garbage when things are < 0 - See https://github.com/linebender/xilem/issues/377 - let min_w_min_h = self.min.height / self.min.width; - let max_w_min_h = self.min.height / self.max.width; - let min_w_max_h = self.max.height / self.min.width; + let min_w_min_h = 0.0 / 0.0; + let max_w_min_h = 0.0 / self.max.width; + let min_w_max_h = self.max.height / 0.0; let max_w_max_h = self.max.height / self.max.width; // When the aspect ratio line crosses the constraints, the closest point must be one of the @@ -219,22 +160,22 @@ impl BoxConstraints { if aspect_ratio > min_w_max_h { // outside max height min width Size { - width: self.min.width, + width: 0.0, height: self.max.height, } } else if aspect_ratio < max_w_min_h { // outside min height max width Size { width: self.max.width, - height: self.min.height, + height: 0.0, } } else if aspect_ratio > min_w_min_h { // hits the constraints on the min width line - if width < self.min.width { + if width < 0.0 { // we take the point on the min width Size { - width: self.min.width, - height: self.min.width * aspect_ratio, + width: 0.0, + height: 0.0 * aspect_ratio, } } else if aspect_ratio < max_w_max_h { // exits through max.width @@ -251,11 +192,11 @@ impl BoxConstraints { } } else { // final case is where we hit constraints on the min height line - if width < self.min.width { + if width < 0.0 { // take the point on the min height Size { - width: self.min.height * aspect_ratio.recip(), - height: self.min.height, + width: 0.0 * aspect_ratio.recip(), + height: 0.0, } } else if aspect_ratio > max_w_max_h { // exit thru max height @@ -278,13 +219,11 @@ impl BoxConstraints { mod tests { use super::*; - fn bc(min_width: f64, min_height: f64, max_width: f64, max_height: f64) -> BoxConstraints { - BoxConstraints::new( - Size::new(min_width, min_height), - Size::new(max_width, max_height), - ) + fn bc(_min_width: f64, _min_height: f64, max_width: f64, max_height: f64) -> BoxConstraints { + BoxConstraints::new(Size::new(max_width, max_height)) } + // TODO - Fix this test #[test] fn constrain_aspect_ratio() { for (bc, aspect_ratio, width, output) in [ @@ -373,7 +312,5 @@ mod tests { fn unbounded() { assert!(!BoxConstraints::UNBOUNDED.is_width_bounded()); assert!(!BoxConstraints::UNBOUNDED.is_height_bounded()); - - assert_eq!(BoxConstraints::UNBOUNDED.min(), Size::ZERO); } } diff --git a/masonry/src/widget/align.rs b/masonry/src/widget/align.rs index 4c91fbfe7..62b75f76c 100644 --- a/masonry/src/widget/align.rs +++ b/masonry/src/widget/align.rs @@ -96,7 +96,7 @@ impl Widget for Align { } fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size { - let size = ctx.run_layout(&mut self.child, &bc.loosen()); + let size = ctx.run_layout(&mut self.child, &bc); log_size_warnings(size); diff --git a/masonry/src/widget/button.rs b/masonry/src/widget/button.rs index 551727e09..af3bfee4a 100644 --- a/masonry/src/widget/button.rs +++ b/masonry/src/widget/button.rs @@ -127,7 +127,7 @@ impl Widget for Button { fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size { let padding = Size::new(LABEL_INSETS.x_value(), LABEL_INSETS.y_value()); - let label_bc = bc.shrink(padding).loosen(); + let label_bc = bc.shrink(padding); let label_size = ctx.run_layout(&mut self.label, &label_bc); diff --git a/masonry/src/widget/flex.rs b/masonry/src/widget/flex.rs index 98e463505..2b50543d8 100644 --- a/masonry/src/widget/flex.rs +++ b/masonry/src/widget/flex.rs @@ -126,7 +126,7 @@ impl Flex { cross_alignment: CrossAxisAlignment::Center, main_alignment: MainAxisAlignment::Start, fill_major_axis: false, - old_bc: BoxConstraints::tight(Size::ZERO), + old_bc: BoxConstraints::new(Size::ZERO), gap: None, } } @@ -701,21 +701,10 @@ impl Axis { } /// Generate constraints with new values on the major axis. - pub(crate) fn constraints( - self, - bc: &BoxConstraints, - min_major: f64, - major: f64, - ) -> BoxConstraints { + pub(crate) fn constraints(self, bc: &BoxConstraints, major: f64) -> BoxConstraints { match self { - Axis::Horizontal => BoxConstraints::new( - Size::new(min_major, bc.min().height), - Size::new(major, bc.max().height), - ), - Axis::Vertical => BoxConstraints::new( - Size::new(bc.min().width, min_major), - Size::new(bc.max().width, major), - ), + Axis::Horizontal => BoxConstraints::new(Size::new(major, bc.max().height)), + Axis::Vertical => BoxConstraints::new(Size::new(bc.max().width, major)), } } } @@ -923,10 +912,10 @@ impl Widget for Flex { fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size { // we loosen our constraints when passing to children. - let loosened_bc = bc.loosen(); + let loosened_bc = bc; // minor-axis values for all children - let mut minor = self.direction.minor(bc.min()); + let mut minor = 0_f64; // these two are calculated but only used if we're baseline aligned let mut max_above_baseline = 0_f64; let mut max_below_baseline = 0_f64; @@ -1021,7 +1010,7 @@ impl Widget for Flex { remainder = desired_major - actual_major; let old_size = ctx.widget_state.layout_rect().size(); - let child_bc = self.direction.constraints(&loosened_bc, 0.0, actual_major); + let child_bc = self.direction.constraints(&loosened_bc, actual_major); let child_size = ctx.run_layout(widget, &child_bc); if old_size != child_size { @@ -1057,8 +1046,8 @@ impl Widget for Flex { (remaining - major_flex).max(0.0) } else { // if we are *not* expected to fill our available space this usually - // means we don't have any extra, unless dictated by our constraints. - (self.direction.major(bc.min()) - (major_non_flex + major_flex)).max(0.0) + // means we don't have any extra + 0.0 }; let mut spacing = Spacing::new(self.main_alignment, extra, self.children.len()); @@ -1099,7 +1088,7 @@ impl Widget for Flex { .pack(self.direction.major(child_size), minor_dim) .into(); if ctx.widget_state.layout_rect().size() != fill_size { - let child_bc = BoxConstraints::tight(fill_size); + let child_bc = BoxConstraints::new(fill_size); //TODO: this is the second call of layout on the same child, which // is bad, because it can lead to exponential increase in layout calls // when used multiple times in the widget hierarchy. diff --git a/masonry/src/widget/grid.rs b/masonry/src/widget/grid.rs index 261e184b5..fd9599770 100644 --- a/masonry/src/widget/grid.rs +++ b/masonry/src/widget/grid.rs @@ -274,7 +274,7 @@ impl Widget for Grid { (child.width as f64 * width_unit - self.grid_spacing).max(0.0), (child.height as f64 * height_unit - self.grid_spacing).max(0.0), ); - let child_bc = BoxConstraints::new(cell_size, cell_size); + let child_bc = BoxConstraints::new(cell_size); let _ = ctx.run_layout(&mut child.widget, &child_bc); ctx.place_child( &mut child.widget, diff --git a/masonry/src/widget/image.rs b/masonry/src/widget/image.rs index adbcc8e96..e9135f830 100644 --- a/masonry/src/widget/image.rs +++ b/masonry/src/widget/image.rs @@ -87,7 +87,7 @@ impl Widget for Image { // the image. let image_size = Size::new(self.image_data.width as f64, self.image_data.height as f64); if image_size.is_zero_area() { - let size = bc.min(); + let size = Size::ZERO; return size; } let image_aspect_ratio = image_size.height / image_size.width; diff --git a/masonry/src/widget/portal.rs b/masonry/src/widget/portal.rs index 6fa5169e0..8331ca406 100644 --- a/masonry/src/widget/portal.rs +++ b/masonry/src/widget/portal.rs @@ -360,10 +360,9 @@ impl Widget for Portal { fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size { // TODO - How Portal handles BoxConstraints is due for a rework - let min_child_size = if self.must_fill { bc.min() } else { Size::ZERO }; let max_child_size = bc.max(); - let child_bc = BoxConstraints::new(min_child_size, max_child_size); + let child_bc = BoxConstraints::new(max_child_size); let content_size = ctx.run_layout(&mut self.child, &child_bc); let portal_size = bc.constrain(content_size); diff --git a/masonry/src/widget/sized_box.rs b/masonry/src/widget/sized_box.rs index af8f874d5..b69bd0702 100644 --- a/masonry/src/widget/sized_box.rs +++ b/masonry/src/widget/sized_box.rs @@ -436,26 +436,17 @@ impl SizedBox { fn child_constraints(&self, bc: &BoxConstraints) -> BoxConstraints { // if we don't have a width/height, we don't change that axis. // if we have a width/height, we clamp it on that axis. - let (min_width, max_width) = match self.width { - Some(width) => { - let w = width.max(bc.min().width).min(bc.max().width); - (w, w) - } - None => (bc.min().width, bc.max().width), + let max_width = match self.width { + Some(width) => width.min(bc.max().width), + None => bc.max().width, }; - let (min_height, max_height) = match self.height { - Some(height) => { - let h = height.max(bc.min().height).min(bc.max().height); - (h, h) - } - None => (bc.min().height, bc.max().height), + let max_height = match self.height { + Some(height) => height.min(bc.max().height), + None => bc.max().height, }; - BoxConstraints::new( - Size::new(min_width, min_height), - Size::new(max_width, max_height), - ) + BoxConstraints::new(Size::new(max_width, max_height)) } #[allow(dead_code)] @@ -583,20 +574,11 @@ mod tests { // TODO - Add WidgetMut tests - #[test] - fn expand() { - let expand = SizedBox::new(Label::new("hello!")).expand(); - let bc = BoxConstraints::tight(Size::new(400., 400.)).loosen(); - let child_bc = expand.child_constraints(&bc); - assert_eq!(child_bc.min(), Size::new(400., 400.,)); - } - #[test] fn no_width() { let expand = SizedBox::new(Label::new("hello!")).height(200.); - let bc = BoxConstraints::tight(Size::new(400., 400.)).loosen(); + let bc = BoxConstraints::new(Size::new(400., 400.)); let child_bc = expand.child_constraints(&bc); - assert_eq!(child_bc.min(), Size::new(0., 200.,)); assert_eq!(child_bc.max(), Size::new(400., 200.,)); } diff --git a/masonry/src/widget/split.rs b/masonry/src/widget/split.rs index 9b96b62cd..17d7651cd 100644 --- a/masonry/src/widget/split.rs +++ b/masonry/src/widget/split.rs @@ -451,14 +451,8 @@ impl Widget for Split { .max(0.0); let child2_width = (reduced_size.width - child1_width).max(0.0); ( - BoxConstraints::new( - Size::new(child1_width, bc.min().height), - Size::new(child1_width, bc.max().height), - ), - BoxConstraints::new( - Size::new(child2_width, bc.min().height), - Size::new(child2_width, bc.max().height), - ), + BoxConstraints::new(Size::new(child1_width, bc.max().height)), + BoxConstraints::new(Size::new(child2_width, bc.max().height)), ) } Axis::Vertical => { @@ -467,14 +461,8 @@ impl Widget for Split { .max(0.0); let child2_height = (reduced_size.height - child1_height).max(0.0); ( - BoxConstraints::new( - Size::new(bc.min().width, child1_height), - Size::new(bc.max().width, child1_height), - ), - BoxConstraints::new( - Size::new(bc.min().width, child2_height), - Size::new(bc.max().width, child2_height), - ), + BoxConstraints::new(Size::new(bc.max().width, child1_height)), + BoxConstraints::new(Size::new(bc.max().width, child2_height)), ) } }; diff --git a/masonry/src/widget/tests/snapshots/masonry__widget__tests__lifecycle_basic__app_creation.snap.new b/masonry/src/widget/tests/snapshots/masonry__widget__tests__lifecycle_basic__app_creation.snap.new new file mode 100644 index 000000000..d9db3f770 --- /dev/null +++ b/masonry/src/widget/tests/snapshots/masonry__widget__tests__lifecycle_basic__app_creation.snap.new @@ -0,0 +1,18 @@ +--- +source: masonry/src/widget/tests/lifecycle_basic.rs +assertion_line: 22 +expression: record +--- +[ + RegisterChildren, + L( + WidgetAdded, + ), + L( + BuildFocusChain, + ), + Layout( + 0.0W×0.0H, + ), + Compose, +]