From 334dd098170d56c004d7a97bdfbbffe6f63f0ebd Mon Sep 17 00:00:00 2001 From: Clark Moody Date: Tue, 26 May 2020 16:11:49 -0500 Subject: [PATCH 1/3] Pane Grid spacing applied prior to rounding On low-DPI screens, the rounding order of operations made it impossible to produce an odd-pixel spacing. Specifying 1, for instance, produced zero space between panes. This approach subtracts half the spacing from the first pane prior to rounding and uses the whole spacing for the second pane size and coordinate. --- native/src/widget/pane_grid/axis.rs | 24 +++++++++++++----------- native/src/widget/pane_grid/node.rs | 22 ++++++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/native/src/widget/pane_grid/axis.rs b/native/src/widget/pane_grid/axis.rs index f0e3f362..7181f9bf 100644 --- a/native/src/widget/pane_grid/axis.rs +++ b/native/src/widget/pane_grid/axis.rs @@ -14,37 +14,39 @@ impl Axis { &self, rectangle: &Rectangle, ratio: f32, - halved_spacing: f32, + spacing: f32, ) -> (Rectangle, Rectangle) { match self { Axis::Horizontal => { - let height_top = (rectangle.height * ratio).round(); - let height_bottom = rectangle.height - height_top; + let height_top = + (rectangle.height * ratio - spacing / 2.0).round(); + let height_bottom = rectangle.height - height_top - spacing; ( Rectangle { - height: height_top - halved_spacing, + height: height_top, ..*rectangle }, Rectangle { - y: rectangle.y + height_top + halved_spacing, - height: height_bottom - halved_spacing, + y: rectangle.y + height_top + spacing, + height: height_bottom, ..*rectangle }, ) } Axis::Vertical => { - let width_left = (rectangle.width * ratio).round(); - let width_right = rectangle.width - width_left; + let width_left = + (rectangle.width * ratio - spacing / 2.0).round(); + let width_right = rectangle.width - width_left - spacing; ( Rectangle { - width: width_left - halved_spacing, + width: width_left, ..*rectangle }, Rectangle { - x: rectangle.x + width_left + halved_spacing, - width: width_right - halved_spacing, + x: rectangle.x + width_left + spacing, + width: width_right, ..*rectangle }, ) diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs index 723ec393..b13c5e26 100644 --- a/native/src/widget/pane_grid/node.rs +++ b/native/src/widget/pane_grid/node.rs @@ -56,7 +56,7 @@ impl Node { let mut regions = HashMap::new(); self.compute_regions( - spacing / 2.0, + spacing, &Rectangle { x: 0.0, y: 0.0, @@ -83,7 +83,7 @@ impl Node { let mut splits = HashMap::new(); self.compute_splits( - spacing / 2.0, + spacing, &Rectangle { x: 0.0, y: 0.0, @@ -185,7 +185,7 @@ impl Node { fn compute_regions( &self, - halved_spacing: f32, + spacing: f32, current: &Rectangle, regions: &mut HashMap, ) { @@ -193,11 +193,10 @@ impl Node { Node::Split { axis, ratio, a, b, .. } => { - let (region_a, region_b) = - axis.split(current, *ratio, halved_spacing); + let (region_a, region_b) = axis.split(current, *ratio, spacing); - a.compute_regions(halved_spacing, ®ion_a, regions); - b.compute_regions(halved_spacing, ®ion_b, regions); + a.compute_regions(spacing, ®ion_a, regions); + b.compute_regions(spacing, ®ion_b, regions); } Node::Pane(pane) => { let _ = regions.insert(*pane, *current); @@ -207,7 +206,7 @@ impl Node { fn compute_splits( &self, - halved_spacing: f32, + spacing: f32, current: &Rectangle, splits: &mut HashMap, ) { @@ -219,13 +218,12 @@ impl Node { b, id, } => { - let (region_a, region_b) = - axis.split(current, *ratio, halved_spacing); + let (region_a, region_b) = axis.split(current, *ratio, spacing); let _ = splits.insert(*id, (*axis, *current, *ratio)); - a.compute_splits(halved_spacing, ®ion_a, splits); - b.compute_splits(halved_spacing, ®ion_b, splits); + a.compute_splits(spacing, ®ion_a, splits); + b.compute_splits(spacing, ®ion_b, splits); } Node::Pane(_) => {} } From 9079014974e7dab83d70d2c08adb1dc50a49629c Mon Sep 17 00:00:00 2001 From: Clark Moody Date: Tue, 26 May 2020 16:47:29 -0500 Subject: [PATCH 2/3] Tests for axis split --- native/src/widget/pane_grid/axis.rs | 87 +++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/native/src/widget/pane_grid/axis.rs b/native/src/widget/pane_grid/axis.rs index 7181f9bf..f8c7b661 100644 --- a/native/src/widget/pane_grid/axis.rs +++ b/native/src/widget/pane_grid/axis.rs @@ -54,3 +54,90 @@ impl Axis { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn split_horizontal() { + let a = Axis::Horizontal; + // rectangle height, spacing, top height, bottom y, bottom height + let cases = vec![ + // Even height, even spacing + (10.0, 2.0, 4.0, 6.0, 4.0), + // Odd height, even spacing + (9.0, 2.0, 4.0, 6.0, 3.0), + // Even height, odd spacing + (10.0, 1.0, 5.0, 6.0, 4.0), + // Odd height, odd spacing + (9.0, 1.0, 4.0, 5.0, 4.0), + ]; + for case in cases { + let (h0, spacing, h1_top, y_bottom, h1_bottom) = case; + let r = Rectangle { + x: 0.0, + y: 0.0, + width: 10.0, + height: h0, + }; + let (top, bottom) = a.split(&r, 0.5, spacing); + assert_eq!( + top, + Rectangle { + height: h1_top, + ..r + } + ); + assert_eq!( + bottom, + Rectangle { + y: y_bottom, + height: h1_bottom, + ..r + } + ); + } + } + + #[test] + fn split_vertical() { + let a = Axis::Vertical; + // rectangle width, spacing, left width, right x, right width + let cases = vec![ + // Even width, even spacing + (10.0, 2.0, 4.0, 6.0, 4.0), + // Odd width, even spacing + (9.0, 2.0, 4.0, 6.0, 3.0), + // Even width, odd spacing + (10.0, 1.0, 5.0, 6.0, 4.0), + // Odd width, odd spacing + (9.0, 1.0, 4.0, 5.0, 4.0), + ]; + for case in cases { + let (w0, spacing, w1_left, x_right, w1_right) = case; + let r = Rectangle { + x: 0.0, + y: 0.0, + width: w0, + height: 10.0, + }; + let (left, right) = a.split(&r, 0.5, spacing); + assert_eq!( + left, + Rectangle { + width: w1_left, + ..r + } + ); + assert_eq!( + right, + Rectangle { + x: x_right, + width: w1_right, + ..r + } + ); + } + } +} From 858eafe22e6f17962c935a3d58749dbd839c46ae Mon Sep 17 00:00:00 2001 From: Clark Moody Date: Wed, 27 May 2020 14:24:33 -0500 Subject: [PATCH 3/3] Structured test cases --- native/src/widget/pane_grid/axis.rs | 205 +++++++++++++++++++--------- 1 file changed, 138 insertions(+), 67 deletions(-) diff --git a/native/src/widget/pane_grid/axis.rs b/native/src/widget/pane_grid/axis.rs index f8c7b661..b3a306d5 100644 --- a/native/src/widget/pane_grid/axis.rs +++ b/native/src/widget/pane_grid/axis.rs @@ -59,85 +59,156 @@ impl Axis { mod tests { use super::*; - #[test] - fn split_horizontal() { - let a = Axis::Horizontal; - // rectangle height, spacing, top height, bottom y, bottom height - let cases = vec![ - // Even height, even spacing - (10.0, 2.0, 4.0, 6.0, 4.0), - // Odd height, even spacing - (9.0, 2.0, 4.0, 6.0, 3.0), - // Even height, odd spacing - (10.0, 1.0, 5.0, 6.0, 4.0), - // Odd height, odd spacing - (9.0, 1.0, 4.0, 5.0, 4.0), - ]; - for case in cases { - let (h0, spacing, h1_top, y_bottom, h1_bottom) = case; - let r = Rectangle { - x: 0.0, - y: 0.0, - width: 10.0, - height: h0, - }; - let (top, bottom) = a.split(&r, 0.5, spacing); - assert_eq!( - top, - Rectangle { - height: h1_top, - ..r - } - ); - assert_eq!( - bottom, - Rectangle { - y: y_bottom, - height: h1_bottom, - ..r - } - ); - } + enum Case { + Horizontal { + overall_height: f32, + spacing: f32, + top_height: f32, + bottom_y: f32, + bottom_height: f32, + }, + Vertical { + overall_width: f32, + spacing: f32, + left_width: f32, + right_x: f32, + right_width: f32, + }, } #[test] - fn split_vertical() { - let a = Axis::Vertical; - // rectangle width, spacing, left width, right x, right width + fn split() { let cases = vec![ + // Even height, even spacing + Case::Horizontal { + overall_height: 10.0, + spacing: 2.0, + top_height: 4.0, + bottom_y: 6.0, + bottom_height: 4.0, + }, + // Odd height, even spacing + Case::Horizontal { + overall_height: 9.0, + spacing: 2.0, + top_height: 4.0, + bottom_y: 6.0, + bottom_height: 3.0, + }, + // Even height, odd spacing + Case::Horizontal { + overall_height: 10.0, + spacing: 1.0, + top_height: 5.0, + bottom_y: 6.0, + bottom_height: 4.0, + }, + // Odd height, odd spacing + Case::Horizontal { + overall_height: 9.0, + spacing: 1.0, + top_height: 4.0, + bottom_y: 5.0, + bottom_height: 4.0, + }, // Even width, even spacing - (10.0, 2.0, 4.0, 6.0, 4.0), + Case::Vertical { + overall_width: 10.0, + spacing: 2.0, + left_width: 4.0, + right_x: 6.0, + right_width: 4.0, + }, // Odd width, even spacing - (9.0, 2.0, 4.0, 6.0, 3.0), + Case::Vertical { + overall_width: 9.0, + spacing: 2.0, + left_width: 4.0, + right_x: 6.0, + right_width: 3.0, + }, // Even width, odd spacing - (10.0, 1.0, 5.0, 6.0, 4.0), + Case::Vertical { + overall_width: 10.0, + spacing: 1.0, + left_width: 5.0, + right_x: 6.0, + right_width: 4.0, + }, // Odd width, odd spacing - (9.0, 1.0, 4.0, 5.0, 4.0), + Case::Vertical { + overall_width: 9.0, + spacing: 1.0, + left_width: 4.0, + right_x: 5.0, + right_width: 4.0, + }, ]; for case in cases { - let (w0, spacing, w1_left, x_right, w1_right) = case; - let r = Rectangle { - x: 0.0, - y: 0.0, - width: w0, - height: 10.0, - }; - let (left, right) = a.split(&r, 0.5, spacing); - assert_eq!( - left, - Rectangle { - width: w1_left, - ..r + match case { + Case::Horizontal { + overall_height, + spacing, + top_height, + bottom_y, + bottom_height, + } => { + let a = Axis::Horizontal; + let r = Rectangle { + x: 0.0, + y: 0.0, + width: 10.0, + height: overall_height, + }; + let (top, bottom) = a.split(&r, 0.5, spacing); + assert_eq!( + top, + Rectangle { + height: top_height, + ..r + } + ); + assert_eq!( + bottom, + Rectangle { + y: bottom_y, + height: bottom_height, + ..r + } + ); } - ); - assert_eq!( - right, - Rectangle { - x: x_right, - width: w1_right, - ..r + Case::Vertical { + overall_width, + spacing, + left_width, + right_x, + right_width, + } => { + let a = Axis::Vertical; + let r = Rectangle { + x: 0.0, + y: 0.0, + width: overall_width, + height: 10.0, + }; + let (left, right) = a.split(&r, 0.5, spacing); + assert_eq!( + left, + Rectangle { + width: left_width, + ..r + } + ); + assert_eq!( + right, + Rectangle { + x: right_x, + width: right_width, + ..r + } + ); } - ); + } } } }