wip: and sweeps right through the codebase

This commit is contained in:
🪞👃🪞 2024-12-31 02:03:16 +01:00
parent d37bd3e0c5
commit c9b09b7dea
16 changed files with 370 additions and 625 deletions

View file

@ -8,46 +8,60 @@ use crate::*;
/// double generic.
macro_rules! content_enum {
($Enum:ident: $($Variant:ident),+ $(,)?) => {
pub enum $Enum<E: Engine, T: Render<E>> {
pub enum $Enum<E: Engine, T: Content<E>> {
_Unused(PhantomData<E>), $($Variant(T)),+
}
impl<E: Engine, T: Render<E>> $Enum<E, T> {
fn content (&self) -> Option<impl Render<E>> {
match self {
Self::_Unused(_) => None,
$(Self::$Variant(content) => Some(content)),+
}
}
}
}
}
/// Defines an enum that transforms its content
/// along either the X axis, the Y axis, or both.
macro_rules! transform_xy {
(|$self:ident : $Enum:ident, $to:ident|$render:expr) => {
($self:ident : $Enum:ident |$to:ident|$area:expr) => {
content_enum!($Enum: X, Y, XY);
impl<E: Engine, T: Render<E>> $Enum<E, T> {
impl<E: Engine, T: Content<E>> $Enum<E, T> {
pub fn x (item: T) -> Self { Self::X(item) }
pub fn y (item: T) -> Self { Self::Y(item) }
pub fn xy (item: T) -> Self { Self::XY(item) }
}
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
fn render (&$self, $to: &mut <E as Engine>::Output) {
$render
impl<E: Engine, T: Content<E>> Content<E> for $Enum<E, T> {
fn content (&self) -> Option<impl Content<E>> {
match self {
Self::_Unused(_) => None,
Self::X(item) => Some(item),
Self::Y(item) => Some(item),
Self::XY(item) => Some(item),
}
}
fn area (&$self, $to: <E as Engine>::Area) -> <E as Engine>::Area {
$area
}
}
}
}
transform_xy!(self: Fill |to|{
let [x0, y0, wmax, hmax] = to.xywh();
if let Some(content) = self.content() {
let [x, y, w, h] = content.area(to).xywh();
return match self {
Self::X(_) => [x0, y, wmax, h],
Self::Y(_) => [x, y0, w, hmax],
Self::XY(_) => [x0, y0, wmax, hmax],
_ => unreachable!()
}.into()
}
return [0.into(), 0.into(), 0.into(), 0.into(),].into()
});
/// Defines an enum that transforms its content parametrically
/// along either the X axis, the Y axis, or both
macro_rules! transform_xy_unit {
(|$self:ident : $Enum:ident, $to:ident|$render:expr) => {
pub enum $Enum<E: Engine, T: Render<E>> {
(|$self:ident : $Enum:ident, $to:ident|$area:expr) => {
pub enum $Enum<E: Engine, T: Content<E>> {
X(E::Unit, T), Y(E::Unit, T), XY(E::Unit, E::Unit, T),
}
impl<E: Engine, T: Render<E>> $Enum<E, T> {
impl<E: Engine, T: Content<E>> $Enum<E, T> {
pub fn x (x: E::Unit, item: T) -> Self { Self::X(x, item) }
pub fn y (y: E::Unit, item: T) -> Self { Self::Y(y, item) }
pub fn xy (x: E::Unit, y: E::Unit, item: T) -> Self { Self::XY(x, y, item) }
@ -66,86 +80,65 @@ macro_rules! transform_xy_unit {
}
}
}
impl<E: Engine, T: Render<E>> $Enum<E, T> {
fn content (&self) -> Option<impl Render<E>> {
impl<E: Engine, T: Content<E>> Content<E> for $Enum<E, T> {
fn content (&self) -> Option<impl Content<E>> {
Some(match self {
Self::X(_, content) => content,
Self::Y(_, content) => content,
Self::XY(_, _, content) => content,
})
}
}
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
fn render (&$self, $to: &mut E::Output) -> Usually<()> {
$render
fn area (&$self, $to: E::Area) -> E::Area {
$area.into()
}
}
}
}
transform_xy!(|self: Fill, to|todo!());
transform_xy_unit!(|self: Fixed, to|{
let [x, y, w, h] = to.area().xywh();
to.render_in(match self {
Self::X(fw, _) => [x, y, fw, h],
Self::Y(fh, _) => [x, y, w, fh],
Self::XY(fw, fh, _) => [x, y, fw, fh],
}, self.content())
transform_xy_unit!(|self: Fixed, to|match self {
Self::X(fw, _) => [to.x(), to.y(), *fw, to.h()],
Self::Y(fh, _) => [to.x(), to.y(), to.w(), *fh],
Self::XY(fw, fh, _) => [to.x(), to.y(), *fw, *fh], // tagn
});
transform_xy_unit!(|self: Shrink, to|to.render_in(
[to.x(), to.y(), to.w().minus(self.dx()), to.h().minus(self.dy())],
self.content()));
transform_xy_unit!(|self: Shrink, to|
[to.x(), to.y(), to.w().minus(self.dx()), to.h().minus(self.dy())]);
transform_xy_unit!(|self: Expand, to|to.render_in(
[to.x(), to.y(), to.w() + self.dx(), to.h() + self.dy()],
self.content()));
transform_xy_unit!(|self: Expand, to|
[to.x(), to.y(), to.w() + self.dx(), to.h() + self.dy()]);
transform_xy_unit!(|self: Min, to|to.render_in(match self {
Self::X(mw, _) => [to.x(), to.y(), to.w().max(mw), to.h()],
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().max(mh)],
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().max(mw), to.h().max(mh)]
}, self.content()));
transform_xy_unit!(|self: Min, to|match self {
Self::X(mw, _) => [to.x(), to.y(), to.w().max(*mw), to.h()],
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().max(*mh)],
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().max(*mw), to.h().max(*mh)]
});
transform_xy_unit!(|self: Max, to|to.render_in(match self {
Self::X(mw, _) => [to.x(), to.y(), to.w().min(mw), to.h()],
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().min(mh)],
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().min(mw), to.h().min(mh)],
}, self.content()));
transform_xy_unit!(|self: Max, to|match self {
Self::X(mw, _) => [to.x(), to.y(), to.w().min(*mw), to.h()],
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().min(*mh)],
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().min(*mw), to.h().min(*mh)],
});
transform_xy_unit!(|self: Push, to|to.render_in(
[to.x() + self.dx(), to.y() + self.dy(), to.w(), to.h()],
self.content()));
transform_xy_unit!(|self: Push, to|
[to.x() + self.dx(), to.y() + self.dy(), to.w(), to.h()]);
transform_xy_unit!(|self: Pull, to|to.render_in(
[to.x().minus(self.dx()), to.y().minus(self.dy()), to.w(), to.h()],
self.content()));
transform_xy_unit!(|self: Pull, to|
[to.x().minus(self.dx()), to.y().minus(self.dy()), to.w(), to.h()]);
transform_xy_unit!(|self: Margin, to|{
let dx = self.dx();
let dy = self.dy();
to.render_in([
to.x().minus(dx),
to.y().minus(dy),
to.w() + dy + dy,
to.h() + dy + dy,
])
[to.x().minus(dx), to.y().minus(dy), to.w() + dy + dy, to.h() + dy + dy]
});
transform_xy_unit!(|self: Padding, to|{
let dx = self.dx();
let dy = self.dy();
to.render_in([
to.x() + dx,
to.y() + dy,
to.w().minus(dy + dy),
to.h().minus(dy + dy),
])
[to.x() + dx, to.y() + dy, to.w().minus(dy + dy), to.h().minus(dy + dy), ]
});
content_enum!(Align: Center, X, Y, NW, N, NE, E, SE, S, SW, W);
impl<E: Engine, T: Render<E>> Align<E, T> {
impl<E: Engine, T: Content<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) }
@ -159,7 +152,7 @@ impl<E: Engine, T: Render<E>> Align<E, T> {
pub fn se (w: T) -> Self { Self::SE(w) }
}
fn align<E: Engine, T: Render<E>, N: Coordinate, R: Area<N> + From<[N;4]>> (align: &Align<E, T>, outer: R, content: R) -> Option<R> {
fn align<E: Engine, T: Content<E>, N: Coordinate, R: Area<N> + From<[N;4]>> (align: &Align<E, T>, outer: R, content: R) -> Option<R> {
if outer.w() < content.w() || outer.h() < content.h() {
None
} else {
@ -182,17 +175,14 @@ fn align<E: Engine, T: Render<E>, N: Coordinate, R: Area<N> + From<[N;4]>> (alig
}
}
impl<E: Engine, T: Render<E>> Render<E> for Align<E, T> {
fn min_size (&self, outer_area: E::Size) -> Perhaps<E::Size> {
self.content().min_size(outer_area)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
impl<E: Engine, T: Content<E>> Content<E> for Align<E, T> {
fn render (&self, to: &mut E::Output) {
let outer_area = to.area();
Ok(if let Some(content_size) = self.min_size(outer_area.wh().into())? {
let content_area = outer_area.clip(content_size);
if let Some(aligned) = align(&self, outer_area.into(), content_area.into()) {
to.render_in(aligned, &self.content())?
if let Some(content) = self.content() {
let inner_area = content.area(outer_area);
if let Some(aligned) = align(&self, outer_area.into(), inner_area.into()) {
to.place(aligned, &content)
}
})
}
}
}