mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
wip: and sweeps right through the codebase
This commit is contained in:
parent
d37bd3e0c5
commit
c9b09b7dea
16 changed files with 370 additions and 625 deletions
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue