mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
191 lines
6.8 KiB
Rust
191 lines
6.8 KiB
Rust
use crate::*;
|
|
use super::*;
|
|
|
|
impl<E: Engine, T: Render<E>> Push<E, T> {
|
|
pub fn inner (&self) -> &T {
|
|
use Push::*;
|
|
match self { X(_, i) => i, Y(_, i) => i, XY(_, _, i) => i, }
|
|
}
|
|
pub fn dx (&self) -> E::Unit {
|
|
use Push::*;
|
|
match self { X(x, _) => *x, Y(_, _) => E::Unit::default(), XY(x, _, _) => *x, }
|
|
}
|
|
pub fn dy (&self) -> E::Unit {
|
|
use Push::*;
|
|
match self { X(_, _) => E::Unit::default(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
|
}
|
|
}
|
|
|
|
impl<E: Engine, T: Render<E>> Render<E> for Push<E, T> {
|
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
self.inner().min_size(to)
|
|
}
|
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
let area = to.area();
|
|
Ok(self.min_size(area.wh().into())?
|
|
.map(|size|to.render_in(match *self {
|
|
Self::X(x, _) => [area.x() + x, area.y(), size.w(), size.h()],
|
|
Self::Y(y, _) => [area.x(), area.y() + y, size.w(), size.h()],
|
|
Self::XY(x, y, _) => [area.x() + x, area.y() + y, size.w(), size.h()],
|
|
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
|
}
|
|
}
|
|
|
|
impl<E: Engine, T: Render<E>> Pull<E, T> {
|
|
pub fn inner (&self) -> &T {
|
|
match self {
|
|
Self::X(_, i) => i,
|
|
Self::Y(_, i) => i,
|
|
Self::XY(_, _, i) => i,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
pub fn dx (&self) -> E::Unit {
|
|
match self {
|
|
Self::X(x, _) => *x,
|
|
Self::Y(_, _) => E::Unit::default(),
|
|
Self::XY(x, _, _) => *x,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
pub fn dy (&self) -> E::Unit {
|
|
match self {
|
|
Self::X(_, _) => E::Unit::default(),
|
|
Self::Y(y, _) => *y,
|
|
Self::XY(_, y, _) => *y,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<E: Engine, T: Render<E>> Render<E> for Pull<E, T> {
|
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
self.inner().min_size(to)
|
|
}
|
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
let area = to.area();
|
|
Ok(self.min_size(area.wh().into())?
|
|
.map(|size|to.render_in(match *self {
|
|
Self::X(x, _) => [area.x().minus(x), area.y(), size.w(), size.h()],
|
|
Self::Y(y, _) => [area.x(), area.y().minus(y), size.w(), size.h()],
|
|
Self::XY(x, y, _) => [area.x().minus(x), area.y().minus(y), size.w(), size.h()],
|
|
_ => unreachable!(),
|
|
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
|
}
|
|
}
|
|
|
|
impl<E: Engine, T: Render<E>> Inset<E, T> {
|
|
pub fn inner (&self) -> &T {
|
|
match self {
|
|
Self::X(_, i) => i,
|
|
Self::Y(_, i) => i,
|
|
Self::XY(_, _, i) => i,
|
|
}
|
|
}
|
|
}
|
|
|
|
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) => 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)
|
|
}
|
|
}
|
|
|
|
|
|
impl<E: Engine, T: Render<E>> Outset<E, T> {
|
|
pub fn inner (&self) -> &T {
|
|
match self {
|
|
Self::X(_, i) => i,
|
|
Self::Y(_, i) => i,
|
|
Self::XY(_, _, i) => i,
|
|
}
|
|
}
|
|
}
|
|
|
|
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) => 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) => 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())?
|
|
}
|
|
})
|
|
}
|
|
}
|