use super::Anchor;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct Area {
pub col: u16,
pub row: u16,
pub width: u16,
pub height: u16,
}
impl Area {
pub(crate) fn is_empty(self) -> bool {
self.width == 0 || self.height == 0
}
pub(crate) fn contains(self, col: u16, row: u16) -> bool {
col >= self.col
&& row >= self.row
&& col.saturating_sub(self.col) < self.width
&& row.saturating_sub(self.row) < self.height
}
pub(crate) fn place(self, width: u16, height: u16, anchor: Anchor) -> Area {
let width = width.min(self.width);
let height = height.min(self.height);
let (col, row) = match anchor {
Anchor::TopLeft => (self.col, self.row),
Anchor::TopRight => (self.col + self.width - width, self.row),
Anchor::BottomLeft => (self.col, self.row + self.height - height),
Anchor::BottomRight => (
self.col + self.width - width,
self.row + self.height - height,
),
Anchor::Center => (
self.col + (self.width - width) / 2,
self.row + (self.height - height) / 2,
),
};
Area {
col,
row,
width,
height,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn box_area() -> Area {
Area {
col: 1,
row: 2,
width: 10,
height: 6,
}
}
fn box_area_with(col: u16, row: u16) -> Area {
Area {
col,
row,
width: 2,
height: 3,
}
}
#[test]
fn place_pins_to_the_anchored_corner() {
let place = |anchor| box_area().place(2, 3, anchor);
assert_eq!(place(Anchor::TopLeft), box_area_with(1, 2));
assert_eq!(place(Anchor::TopRight), box_area_with(9, 2));
assert_eq!(place(Anchor::BottomLeft), box_area_with(1, 5));
assert_eq!(place(Anchor::BottomRight), box_area_with(9, 5));
assert_eq!(
place(Anchor::Center),
box_area_with(5, 3),
"the footprint must sit in the middle of the box"
);
}
#[test]
fn place_clips_a_larger_footprint_to_the_box() {
assert_eq!(
box_area().place(u16::MAX, u16::MAX, Anchor::BottomRight),
box_area()
);
}
}