use crate::geometry::*;
pub trait Placement {
fn place(&self, window: Window) -> Window;
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Place;
impl Placement for Place {
fn place(&self, window: Window) -> Window {
window
}
}
pub trait AnchorPlaced<A> {
fn anchor_left(self, anchor: u16) -> A;
fn left_size(self, size: u16) -> A;
fn anchor_right(self, anchor: u16) -> A;
fn right_size(self, size: u16) -> A;
fn anchor_top(self, anchor: u16) -> A;
fn top_size(self, size: u16) -> A;
fn anchor_bottom(self, anchor: u16) -> A;
fn bottom_size(self, size: u16) -> A;
fn fill(self) -> A;
}
impl Place {
pub fn anchor_left(self, anchor: u16) -> AnchorPlacement {
AnchorPlacement::default().anchor_left(anchor)
}
pub fn left_size(self, size: u16) -> AnchorPlacement {
AnchorPlacement::default().left_size(size)
}
pub fn anchor_right(self, anchor: u16) -> AnchorPlacement {
AnchorPlacement::default().anchor_right(anchor)
}
pub fn right_size(self, size: u16) -> AnchorPlacement {
AnchorPlacement::default().right_size(size)
}
pub fn anchor_top(self, anchor: u16) -> AnchorPlacement {
AnchorPlacement::default().anchor_top(anchor)
}
pub fn top_size(self, size: u16) -> AnchorPlacement {
AnchorPlacement::default().top_size(size)
}
pub fn anchor_bottom(self, anchor: u16) -> AnchorPlacement {
AnchorPlacement::default().anchor_bottom(anchor)
}
pub fn bottom_size(self, size: u16) -> AnchorPlacement {
AnchorPlacement::default().bottom_size(size)
}
pub fn fill(self) -> AnchorPlacement {
AnchorPlacement::default()
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AnchorPlacement {
left: Edge<X>,
top: Edge<Y>,
right: Edge<X>,
bottom: Edge<Y>,
}
impl AnchorPlacement {
pub fn anchor_left(mut self, anchor: u16) -> Self {
self.left = Edge::Anchor(x(anchor));
self
}
pub fn left_size(mut self, size: u16) -> Self {
self.left = Edge::Size(x(size));
self
}
pub fn anchor_right(mut self, anchor: u16) -> Self {
self.right = Edge::Anchor(x(anchor));
self
}
pub fn right_size(mut self, size: u16) -> Self {
self.right = Edge::Size(x(size));
self
}
pub fn anchor_top(mut self, anchor: u16) -> Self {
self.top = Edge::Anchor(y(anchor));
self
}
pub fn top_size(mut self, size: u16) -> Self {
self.top = Edge::Size(y(size));
self
}
pub fn anchor_bottom(mut self, anchor: u16) -> Self {
self.bottom = Edge::Anchor(y(anchor));
self
}
pub fn bottom_size(mut self, size: u16) -> Self {
self.bottom = Edge::Size(y(size));
self
}
pub fn fill(self) -> AnchorPlacement {
AnchorPlacement::default()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
enum Edge<T> {
Anchor(T),
Size(T),
}
impl<T> Default for Edge<T>
where
T: Default,
{
fn default() -> Self {
Edge::Anchor(Default::default())
}
}
impl Placement for AnchorPlacement {
fn place(&self, w: Window) -> Window {
let s = w.size;
let x = match (self.left, self.right) {
(Edge::Size(l), Edge::Size(r)) => (s.x / 2 - l, l + r),
(Edge::Size(l), Edge::Anchor(r)) => (s.x - l - r, l),
(Edge::Anchor(l), Edge::Size(r)) => (l, r),
(Edge::Anchor(l), Edge::Anchor(r)) => (l, s.x - l - r),
};
let y = match (self.top, self.bottom) {
(Edge::Size(l), Edge::Size(r)) => (s.y / 2 - l, l + r),
(Edge::Size(l), Edge::Anchor(r)) => (s.y - l - r, l),
(Edge::Anchor(l), Edge::Size(r)) => (l, r),
(Edge::Anchor(l), Edge::Anchor(r)) => (l, s.y - l - r),
};
let placement = window(point(x.0, y.0), point(x.1, y.1));
w.crop(&placement)
}
}
#[test]
fn test_anchor_placement() {
let sut = AnchorPlacement::default().anchor_top(0).bottom_size(1);
let w = sut.place(window(point(x(0), y(0)), point(x(5), y(5))));
assert_eq!(w, window(point(x(0), y(0)), point(x(5), y(1))));
let sut = AnchorPlacement::default().top_size(1).anchor_bottom(0);
let w = sut.place(window(point(x(0), y(0)), point(x(5), y(5))));
assert_eq!(w, window(point(x(0), y(4)), point(x(5), y(1))));
let sut = AnchorPlacement::default().anchor_top(1).anchor_bottom(1);
let w = sut.place(window(point(x(2), y(2)), point(x(5), y(5))));
assert_eq!(w, window(point(x(2), y(3)), point(x(5), y(3))));
}