diff --git a/layout/src/bsp.rs b/layout/src/bsp.rs deleted file mode 100644 index b9e50ffd..00000000 --- a/layout/src/bsp.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::*; - -/// Renders multiple things on top of each other, -#[macro_export] macro_rules! lay { - ($($expr:expr),* $(,)?) => {{ - let bsp = (); - $(let bsp = Bsp::b(bsp, $expr);)*; - bsp - }} -} - -/// Stack southward. -#[macro_export] macro_rules! col { - ($($expr:expr),* $(,)?) => {{ - let bsp = (); - $(let bsp = Bsp::s(bsp, $expr);)*; - bsp - }}; -} - -/// Stack northward. -#[macro_export] macro_rules! col_up { - ($($expr:expr),* $(,)?) => {{ - let bsp = (); - $(let bsp = Bsp::n(bsp, $expr);)*; - bsp - }} -} - -/// Stack eastward. -#[macro_export] macro_rules! row { - ($($expr:expr),* $(,)?) => {{ - let bsp = (); - $(let bsp = Bsp::e(bsp, $expr);)*; - bsp - }}; -} - -pub enum Bsp, Y: Content> { - /// X is north of Y - North(Option, Option, Option), - /// X is south of Y - South(Option, Option, Option), - /// X is east of Y - East(Option, Option, Option), - /// X is west of Y - West(Option, Option, Option), - /// X is above Y - Above(Option, Option), - /// X is below Y - Below(Option, Option), - /// Should be avoided. - Null(PhantomData), -} - -impl, Y: Content> Bsp { - pub fn n (x: X, y: Y) -> Self { Self::North(None, Some(x), Some(y)) } - pub fn s (x: X, y: Y) -> Self { Self::South(None, Some(x), Some(y)) } - pub fn e (x: X, y: Y) -> Self { Self::East(None, Some(x), Some(y)) } - pub fn w (x: X, y: Y) -> Self { Self::West(None, Some(x), Some(y)) } - pub fn a (x: X, y: Y) -> Self { Self::Above(Some(x), Some(y)) } - pub fn b (x: X, y: Y) -> Self { Self::Below(Some(x), Some(y)) } - - pub fn areas (&self, outer: E::Area) -> [E::Area;2] { - let [x, y, w, h] = outer.xywh(); - match self { - Self::Null(_) => [[x, y, 0.into(), 0.into()].into(), [x, y, 0.into(), 0.into()].into()], - Self::Above(a, b) | Self::Below(a, b) => [a.layout(outer), b.layout(outer)], - Self::North(_, a, b) => { - let a = a.layout(outer); - let b = b.layout([x, y, w, h.minus(a.h())].into()); - [a, b] - } - Self::South(_, a, b) => { - let a = a.layout(outer); - let b = b.layout([x, y + a.h(), w, h.minus(a.h())].into()); - [a, b] - }, - Self::East(_, a, b) => { - let a = a.layout(outer); - let b = b.layout([x + a.w(), y, w.minus(a.w()), h].into()); - [a, b] - }, - Self::West(_, a, b) => { - let a = a.layout(outer); - let b = b.layout([x, y, w.minus(a.w()), h].into()); - [a, b] - }, - } - } -} - -impl, Y: Content> Default for Bsp { - fn default () -> Self { - Self::Null(Default::default()) - } -} - -impl, Y: Content> Content for Bsp { - fn layout (&self, outer: E::Area) -> E::Area { - let [a, b] = self.areas(outer); - let [x, y] = outer.center(); - match self { - Self::Null(_) => - [x, y, 0.into(), 0.into()], - Self::North(_, _, _) => - [a.x().min(b.x()), a.y().min(b.y()), a.w().max(b.w()), a.h() + b.h()], - Self::South(_, _, _) => - [a.x().min(b.x()), a.y().min(b.y()), a.w().max(b.w()), a.h() + b.h()], - Self::East(_, _, _) => - [a.x().min(b.x()), a.y().min(b.y()), a.w() + b.w(), a.h().max(b.h())], - Self::West(_, _, _) => - [a.x().min(b.x()), a.y().min(b.y()), a.w() + b.w(), a.h().max(b.h())], - Self::Above(_, _) | Self::Below(_, _) => - [a.x().min(b.x()), a.y().min(b.y()), a.w().max(b.w()), a.h().max(b.h())] - }.into() - } - fn render (&self, to: &mut E::Output) { - let [area_a, area_b] = self.areas(to.area()); - match self { - Self::North(_, a, b) | - Self::South(_, a, b) | - Self::East(_, a, b) | - Self::West(_, a, b) | - Self::Above(a, b) | - Self::Below(a, b) => { - to.place(area_a, a); - to.place(area_b, b); - }, - _ => {}, - } - } -} diff --git a/layout/src/direction.rs b/layout/src/direction.rs index 1b1f7c14..37b79eb7 100644 --- a/layout/src/direction.rs +++ b/layout/src/direction.rs @@ -1,52 +1,83 @@ use crate::*; +pub use self::Direction::*; /// A cardinal direction. #[derive(Copy, Clone, PartialEq)] -pub enum Direction { North, South, West, East, } - -pub use self::Direction::*; +pub enum Direction { North, South, East, West, Above, Below } impl Direction { - pub fn is_north (&self) -> bool { matches!(self, Self::North) } - pub fn is_south (&self) -> bool { matches!(self, Self::South) } - pub fn is_east (&self) -> bool { matches!(self, Self::West) } - pub fn is_west (&self) -> bool { matches!(self, Self::East) } - /// Return next direction clockwise - pub fn cw (&self) -> Self { - match self { - Self::North => Self::East, - Self::South => Self::West, - Self::West => Self::North, - Self::East => Self::South, - } - } - /// Return next direction counterclockwise01. - pub fn ccw (&self) -> Self { - match self { - Self::North => Self::West, - Self::South => Self::East, - Self::West => Self::South, - Self::East => Self::North, - } - } pub fn split_fixed (self, area: impl Area, a: N) -> ([N;4],[N;4]) { + let [x, y, w, h] = area.xywh(); match self { - North => ( - [area.x(), (area.y()+area.h()).minus(a), area.w(), a], - [area.x(), area.y(), area.w(), area.h().minus(a)], - ), - South => ( - [area.x(), area.y(), area.w(), a], - [area.x(), area.y() + a, area.w(), area.h().minus(a)], - ), - East => ( - [area.x(), area.y(), a, area.h()], - [area.x() + a, area.y(), area.w().minus(a), area.h()], - ), - West => ( - [area.x() + area.w() - a, area.y(), a, area.h()], - [area.x(), area.y(), area.w() - a, area.h()], - ), + North => ([x, (y+h).minus(a), w, a], [x, y, w, h.minus(a)]), + South => ([x, y, w, a], [x, y + a, w, h.minus(a)]), + East => ([x, y, a, h], [x + a, y, w.minus(a), h]), + West => ([(x+w).minus(a), y, a, h], [x, y, w - a, h]), + Above | Below => (area.xywh(), area.xywh()) } } } + +pub struct Bsp, Y: Content>(Direction, X, Y, PhantomData); + +impl, B: Content> Bsp { + pub fn n (a: A, b: B) -> Self { Self(North, a, b, Default::default()) } + pub fn s (a: A, b: B) -> Self { Self(South, a, b, Default::default()) } + pub fn e (a: A, b: B) -> Self { Self(East, a, b, Default::default()) } + pub fn w (a: A, b: B) -> Self { Self(West, a, b, Default::default()) } + pub fn a (a: A, b: B) -> Self { Self(Above, a, b, Default::default()) } + pub fn b (a: A, b: B) -> Self { Self(Below, a, b, Default::default()) } + pub fn contents (&self) -> (&A, &B) { (&self.1, &self.2) } + pub fn areas (&self, outer: E::Area) -> [E::Area;2] { + let [x, y, w, h] = outer.xywh(); + let (a, b) = self.contents(); + let a = a.layout(outer); + let b = match self.0 { + North => b.layout([x, y, w, h.minus(a.h())].into()), + South => b.layout([x, y + a.h(), w, h.minus(a.h())].into()), + East => b.layout([x + a.w(), y, w.minus(a.w()), h].into()), + West => b.layout([x, y, w.minus(a.w()), h].into()), + Above | Below => b.layout(outer), + }; + [a, b] + } +} + +impl, B: Content> Content for Bsp { + fn layout (&self, outer: E::Area) -> E::Area { + let [a, b] = self.areas(outer); + let [ax, ay, aw, ah] = a.xywh(); + let [bx, by, bw, bh] = b.xywh(); + match self.0 { + North | South => [ax.min(bx), ay.min(by), aw.max(bw), ah + bh ], + East | West => [ax.min(bx), ay.min(by), aw + bw, ah.max(bh)], + Above | Below => [ax.min(bx), ay.min(by), aw.max(bw), ah.max(bh)], + }.into() + } + fn render (&self, to: &mut E::Output) { + let [area_a, area_b] = self.areas(to.area()); + let (a, b) = self.contents(); + to.place(area_a, a); + to.place(area_b, b); + } +} + +/// Renders multiple things on top of each other, +#[macro_export] macro_rules! lay { + ($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::b(bsp, $expr);)*; bsp }} +} + +/// Stack southward. +#[macro_export] macro_rules! col { + ($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::s(bsp, $expr);)*; bsp }}; +} + +/// Stack northward. +#[macro_export] macro_rules! col_up { + ($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::n(bsp, $expr);)*; bsp }} +} + +/// Stack eastward. +#[macro_export] macro_rules! row { + ($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::e(bsp, $expr);)*; bsp }}; +} diff --git a/layout/src/lib.rs b/layout/src/lib.rs index 0f293e73..72b180bc 100644 --- a/layout/src/lib.rs +++ b/layout/src/lib.rs @@ -1,7 +1,6 @@ //mod collection; pub use self::collection::*; mod align; pub use self::align::*; -mod bsp; pub use self::bsp::*; mod direction; pub use self::direction::*; mod measure; pub use self::measure::*; mod ops; pub use self::ops::*;