241 lines
7.1 KiB
Rust
241 lines
7.1 KiB
Rust
use crate::Rectangle;
|
|
|
|
/// A fixed reference line for the measurement of coordinates.
|
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
|
pub enum Axis {
|
|
/// The horizontal axis: —
|
|
Horizontal,
|
|
/// The vertical axis: |
|
|
Vertical,
|
|
}
|
|
|
|
impl Axis {
|
|
/// Splits the provided [`Rectangle`] on the current [`Axis`] with the
|
|
/// given `ratio` and `spacing`.
|
|
pub fn split(
|
|
&self,
|
|
rectangle: &Rectangle,
|
|
ratio: f32,
|
|
spacing: f32,
|
|
) -> (Rectangle, Rectangle) {
|
|
match self {
|
|
Axis::Horizontal => {
|
|
let height_top =
|
|
(rectangle.height * ratio - spacing / 2.0).round();
|
|
let height_bottom = rectangle.height - height_top - spacing;
|
|
|
|
(
|
|
Rectangle {
|
|
height: height_top,
|
|
..*rectangle
|
|
},
|
|
Rectangle {
|
|
y: rectangle.y + height_top + spacing,
|
|
height: height_bottom,
|
|
..*rectangle
|
|
},
|
|
)
|
|
}
|
|
Axis::Vertical => {
|
|
let width_left =
|
|
(rectangle.width * ratio - spacing / 2.0).round();
|
|
let width_right = rectangle.width - width_left - spacing;
|
|
|
|
(
|
|
Rectangle {
|
|
width: width_left,
|
|
..*rectangle
|
|
},
|
|
Rectangle {
|
|
x: rectangle.x + width_left + spacing,
|
|
width: width_right,
|
|
..*rectangle
|
|
},
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Calculates the bounds of the split line in a [`Rectangle`] region.
|
|
pub fn split_line_bounds(
|
|
&self,
|
|
rectangle: Rectangle,
|
|
ratio: f32,
|
|
spacing: f32,
|
|
) -> Rectangle {
|
|
match self {
|
|
Axis::Horizontal => Rectangle {
|
|
x: rectangle.x,
|
|
y: (rectangle.y + rectangle.height * ratio - spacing / 2.0)
|
|
.round(),
|
|
width: rectangle.width,
|
|
height: spacing,
|
|
},
|
|
Axis::Vertical => Rectangle {
|
|
x: (rectangle.x + rectangle.width * ratio - spacing / 2.0)
|
|
.round(),
|
|
y: rectangle.y,
|
|
width: spacing,
|
|
height: rectangle.height,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
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() {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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
|
|
}
|
|
);
|
|
}
|
|
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
|
|
}
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|