detach all layout constructors from engine

This commit is contained in:
🪞👃🪞 2024-12-30 13:48:51 +01:00
parent 61b447403b
commit e0e680eb7c
19 changed files with 487 additions and 520 deletions

View file

@ -1,59 +1,18 @@
use crate::*;
impl<E: Engine> LayoutPushPull<E> for E {}
pub trait LayoutPushPull<E: Engine> {
fn push_x <W: Render<E>> (x: E::Unit, w: W) -> Push<E, W> {
Push::X(x, w)
}
fn push_y <W: Render<E>> (y: E::Unit, w: W) -> Push<E, W> {
Push::Y(y, w)
}
fn push_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Push<E, W> {
Push::XY(x, y, w)
}
fn pull_x <W: Render<E>> (x: E::Unit, w: W) -> Pull<E, W> {
Pull::X(x, w)
}
fn pull_y <W: Render<E>> (y: E::Unit, w: W) -> Pull<E, W> {
Pull::Y(y, w)
}
fn pull_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Pull<E, W> {
Pull::XY(x, y, w)
}
}
/// Increment origin point of drawing area
pub enum Push<E: Engine, T: Render<E>> {
/// Move origin to the right
X(E::Unit, T),
/// Move origin downwards
Y(E::Unit, T),
/// Move origin to the right and downwards
XY(E::Unit, E::Unit, T),
}
use super::*;
impl<E: Engine, T: Render<E>> Push<E, T> {
pub fn inner (&self) -> &T {
match self {
Self::X(_, i) => i,
Self::Y(_, i) => i,
Self::XY(_, _, i) => i,
}
use Push::*;
match self { X(_, i) => i, Y(_, i) => i, XY(_, _, i) => i, }
}
pub fn x (&self) -> E::Unit {
match self {
Self::X(x, _) => *x,
Self::Y(_, _) => E::Unit::default(),
Self::XY(x, _, _) => *x,
}
pub fn dx (&self) -> E::Unit {
use Push::*;
match self { X(x, _) => *x, Y(_, _) => E::Unit::default(), XY(x, _, _) => *x, }
}
pub fn y (&self) -> E::Unit {
match self {
Self::X(_, _) => E::Unit::default(),
Self::Y(y, _) => *y,
Self::XY(_, y, _) => *y,
}
pub fn dy (&self) -> E::Unit {
use Push::*;
match self { X(_, _) => E::Unit::default(), Y(y, _) => *y, XY(_, y, _) => *y, }
}
}
@ -72,17 +31,6 @@ impl<E: Engine, T: Render<E>> Render<E> for Push<E, T> {
}
}
/// Decrement origin point of drawing area
pub enum Pull<E: Engine, T: Render<E>> {
_Unused(PhantomData<E>),
/// Move origin to the right
X(E::Unit, T),
/// Move origin downwards
Y(E::Unit, T),
/// Move origin to the right and downwards
XY(E::Unit, E::Unit, T),
}
impl<E: Engine, T: Render<E>> Pull<E, T> {
pub fn inner (&self) -> &T {
match self {
@ -92,7 +40,7 @@ impl<E: Engine, T: Render<E>> Pull<E, T> {
_ => unreachable!(),
}
}
pub fn x (&self) -> E::Unit {
pub fn dx (&self) -> E::Unit {
match self {
Self::X(x, _) => *x,
Self::Y(_, _) => E::Unit::default(),
@ -100,7 +48,7 @@ impl<E: Engine, T: Render<E>> Pull<E, T> {
_ => unreachable!(),
}
}
pub fn y (&self) -> E::Unit {
pub fn dy (&self) -> E::Unit {
match self {
Self::X(_, _) => E::Unit::default(),
Self::Y(y, _) => *y,
@ -126,40 +74,6 @@ impl<E: Engine, T: Render<E>> Render<E> for Pull<E, T> {
}
}
impl<E: Engine + LayoutPushPull<E> + LayoutShrinkGrow<E>> LayoutInsetOutset<E> for E {}
pub trait LayoutInsetOutset<E: Engine>: LayoutPushPull<E> + LayoutShrinkGrow<E> {
fn inset_x <W: Render<E>> (x: E::Unit, w: W) -> Inset<E, W> {
Inset::X(x, w)
}
fn inset_y <W: Render<E>> (y: E::Unit, w: W) -> Inset<E, W> {
Inset::Y(y, w)
}
fn inset_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Inset<E, W> {
Inset::XY(x, y, w)
}
fn outset_x <W: Render<E>> (x: E::Unit, w: W) -> Outset<E, W> {
Outset::X(x, w)
}
fn outset_y <W: Render<E>> (y: E::Unit, w: W) -> Outset<E, W> {
Outset::Y(y, w)
}
fn outset_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Outset<E, W> {
Outset::XY(x, y, w)
}
}
/// Shrink from each side
pub enum Inset<E: Engine, T> {
/// Decrease width
X(E::Unit, T),
/// Decrease height
Y(E::Unit, T),
/// Decrease width and height
XY(E::Unit, E::Unit, T),
}
impl<E: Engine, T: Render<E>> Inset<E, T> {
pub fn inner (&self) -> &T {
match self {
@ -173,23 +87,13 @@ impl<E: Engine, T: Render<E>> Inset<E, T> {
impl<E: Engine, T: Render<E>> Render<E> for Inset<E, T> {
fn render (&self, to: &mut E::Output) -> Usually<()> {
match self {
Self::X(x, inner) => E::push_x(*x, E::shrink_x(*x, inner)),
Self::Y(y, inner) => E::push_y(*y, E::shrink_y(*y, inner)),
Self::XY(x, y, inner) => E::push_xy(*x, *y, E::shrink_xy(*x, *y, inner)),
Self::X(x, inner) => Push::x(*x, Shrink::x(*x, inner)),
Self::Y(y, inner) => Push::y(*y, Shrink::y(*y, inner)),
Self::XY(x, y, inner) => Push::xy(*x, *y, Shrink::xy(*x, *y, inner)),
}.render(to)
}
}
/// Grow on each side
pub enum Outset<E: Engine, T: Render<E>> {
/// Increase width
X(E::Unit, T),
/// Increase height
Y(E::Unit, T),
/// Increase width and height
XY(E::Unit, E::Unit, T),
}
impl<E: Engine, T: Render<E>> Outset<E, T> {
pub fn inner (&self) -> &T {
@ -204,16 +108,84 @@ impl<E: Engine, T: Render<E>> Outset<E, T> {
impl<E: Engine, T: Render<E>> Render<E> for Outset<E, T> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
match *self {
Self::X(x, ref inner) => E::grow_x(x + x, inner),
Self::Y(y, ref inner) => E::grow_y(y + y, inner),
Self::XY(x, y, ref inner) => E::grow_xy(x + x, y + y, inner),
Self::X(x, ref inner) => Grow::x(x + x, inner),
Self::Y(y, ref inner) => Grow::y(y + y, inner),
Self::XY(x, y, ref inner) => Grow::xy(x + x, y + y, inner),
}.min_size(to)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
match *self {
Self::X(x, ref inner) => E::push_x(x, inner),
Self::Y(y, ref inner) => E::push_y(y, inner),
Self::XY(x, y, ref inner) => E::push_xy(x, y, inner),
Self::X(x, ref inner) => Push::x(x, inner),
Self::Y(y, ref inner) => Push::y(y, inner),
Self::XY(x, y, ref inner) => Push::xy(x, y, inner),
}.render(to)
}
}
impl<E: Engine, T: Render<E>> Align<E, T> {
pub fn c (w: T) -> Self { Self::Center(w) }
pub fn x (w: T) -> Self { Self::X(w) }
pub fn y (w: T) -> Self { Self::Y(w) }
pub fn n (w: T) -> Self { Self::N(w) }
pub fn s (w: T) -> Self { Self::S(w) }
pub fn e (w: T) -> Self { Self::E(w) }
pub fn w (w: T) -> Self { Self::W(w) }
pub fn nw (w: T) -> Self { Self::NW(w) }
pub fn sw (w: T) -> Self { Self::SW(w) }
pub fn ne (w: T) -> Self { Self::NE(w) }
pub fn se (w: T) -> Self { Self::SE(w) }
pub fn inner (&self) -> &T {
match self {
Self::Center(inner) => inner,
Self::X(inner) => inner,
Self::Y(inner) => inner,
Self::NW(inner) => inner,
Self::N(inner) => inner,
Self::NE(inner) => inner,
Self::W(inner) => inner,
Self::E(inner) => inner,
Self::SW(inner) => inner,
Self::S(inner) => inner,
Self::SE(inner) => inner,
_ => unreachable!(),
}
}
}
fn align<E: Engine, T: Render<E>, N: Coordinate, R: Area<N> + From<[N;4]>> (align: &Align<E, T>, outer: R, inner: R) -> Option<R> {
if outer.w() < inner.w() || outer.h() < inner.h() {
None
} else {
let [ox, oy, ow, oh] = outer.xywh();
let [ix, iy, iw, ih] = inner.xywh();
Some(match align {
Align::Center(_) => [ox + (ow - iw) / 2.into(), oy + (oh - ih) / 2.into(), iw, ih,].into(),
Align::X(_) => [ox + (ow - iw) / 2.into(), iy, iw, ih,].into(),
Align::Y(_) => [ix, oy + (oh - ih) / 2.into(), iw, ih,].into(),
Align::NW(_) => [ox, oy, iw, ih,].into(),
Align::N(_) => [ox + (ow - iw) / 2.into(), oy, iw, ih,].into(),
Align::NE(_) => [ox + ow - iw, oy, iw, ih,].into(),
Align::W(_) => [ox, oy + (oh - ih) / 2.into(), iw, ih,].into(),
Align::E(_) => [ox + ow - iw, oy + (oh - ih) / 2.into(), iw, ih,].into(),
Align::SW(_) => [ox, oy + oh - ih, iw, ih,].into(),
Align::S(_) => [ox + (ow - iw) / 2.into(), oy + oh - ih, iw, ih,].into(),
Align::SE(_) => [ox + ow - iw, oy + oh - ih, iw, ih,].into(),
_ => unreachable!()
})
}
}
impl<E: Engine, T: Render<E>> Render<E> for Align<E, T> {
fn min_size (&self, outer_area: E::Size) -> Perhaps<E::Size> {
self.inner().min_size(outer_area)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
let outer_area = to.area();
Ok(if let Some(inner_size) = self.min_size(outer_area.wh().into())? {
let inner_area = outer_area.clip(inner_size);
if let Some(aligned) = align(&self, outer_area.into(), inner_area.into()) {
to.render_in(aligned, self.inner())?
}
})
}
}