mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-09 21:26:43 +01:00
wip3 (25e): woohoohoo
This commit is contained in:
parent
3de89bf4fd
commit
36280ce9b7
40 changed files with 1607 additions and 1412 deletions
1
crates/tek_layout/README.md
Normal file
1
crates/tek_layout/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
manja s grozde i ikebana s chiaroscuro
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutAlign<E> for W {}
|
||||
impl<E: Engine> LayoutAlign<E> for E {}
|
||||
|
||||
pub trait LayoutAlign<E: Engine>: Render<E> + Sized {
|
||||
fn align_x (self) -> Align<Self> { Align::X(self) }
|
||||
fn align_y (self) -> Align<Self> { Align::Y(self) }
|
||||
fn align_center (self) -> Align<Self> { Align::Center(self) }
|
||||
fn align_n (self) -> Align<Self> { Align::N(self) }
|
||||
fn align_s (self) -> Align<Self> { Align::S(self) }
|
||||
fn align_e (self) -> Align<Self> { Align::E(self) }
|
||||
fn align_w (self) -> Align<Self> { Align::W(self) }
|
||||
fn align_nw (self) -> Align<Self> { Align::NW(self) }
|
||||
fn align_sw (self) -> Align<Self> { Align::SW(self) }
|
||||
fn align_ne (self) -> Align<Self> { Align::NE(self) }
|
||||
fn align_se (self) -> Align<Self> { Align::SE(self) }
|
||||
pub trait LayoutAlign<E: Engine> {
|
||||
fn center_x <W: Render<E>> (w: W) -> Align<W> { Align::X(w) }
|
||||
fn center_y <W: Render<E>> (w: W) -> Align<W> { Align::Y(w) }
|
||||
fn center <W: Render<E>> (w: W) -> Align<W> { Align::Center(w) }
|
||||
fn at_n <W: Render<E>> (w: W) -> Align<W> { Align::N(w) }
|
||||
fn at_s <W: Render<E>> (w: W) -> Align<W> { Align::S(w) }
|
||||
fn at_e <W: Render<E>> (w: W) -> Align<W> { Align::E(w) }
|
||||
fn at_w <W: Render<E>> (w: W) -> Align<W> { Align::W(w) }
|
||||
fn at_nw <W: Render<E>> (w: W) -> Align<W> { Align::NW(w) }
|
||||
fn at_sw <W: Render<E>> (w: W) -> Align<W> { Align::SW(w) }
|
||||
fn at_ne <W: Render<E>> (w: W) -> Align<W> { Align::NE(w) }
|
||||
fn at_se <W: Render<E>> (w: W) -> Align<W> { Align::SE(w) }
|
||||
}
|
||||
|
||||
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||
|
|
|
|||
|
|
@ -1,54 +1,78 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, R: Render<E>> LayoutBsp<E> for R {}
|
||||
impl<E: Engine> LayoutBspStatic<E> for E {}
|
||||
|
||||
pub trait LayoutBsp<E: Engine>: Render<E> + Sized {
|
||||
fn when (self, cond: bool) -> If<E, Self> {
|
||||
If(Default::default(), cond, self)
|
||||
pub trait LayoutBspStatic<E: Engine>: {
|
||||
fn over <A: Render<E>, B: Render<E>> (a: A, b: B) -> Over<E, A, B> {
|
||||
Over(Default::default(), a, b)
|
||||
}
|
||||
fn or <B: Render<E>> (self, cond: bool, other: B) -> Either<E, Self, B> {
|
||||
Either(Default::default(), cond, self, other)
|
||||
fn under <A: Render<E>, B: Render<E>> (a: A, b: B) -> Under<E, A, B> {
|
||||
Under(Default::default(), a, b)
|
||||
}
|
||||
fn over <B: Render<E>> (self, other: B) -> Over<E, Self, B> {
|
||||
Over(Default::default(), self, other)
|
||||
fn to_north <A: Render<E>, B: Render<E>> (a: A, b: B) -> ToNorth<E, A, B> {
|
||||
ToNorth(None, a, b)
|
||||
}
|
||||
fn under <B: Render<E>> (self, other: B) -> Under<E, Self, B> {
|
||||
Under(Default::default(), self, other)
|
||||
fn to_south <A: Render<E>, B: Render<E>> (a: A, b: B) -> ToSouth<E, A, B> {
|
||||
ToSouth(None, a, b)
|
||||
}
|
||||
fn north_of <B: Render<E>> (self, other: B) -> North<E, Self, B> {
|
||||
North(Default::default(), self, other)
|
||||
fn to_east <A: Render<E>, B: Render<E>> (a: A, b: B) -> ToEast<E, A, B> {
|
||||
ToEast(None, a, b)
|
||||
}
|
||||
fn south_of <B: Render<E>> (self, other: B) -> South<E, Self, B> {
|
||||
South(Default::default(), self, other)
|
||||
}
|
||||
fn east_of <B: Render<E>> (self, other: B) -> East<E, Self, B> {
|
||||
East(Default::default(), self, other)
|
||||
}
|
||||
fn west_of <B: Render<E>> (self, other: B) -> West<E, Self, B> {
|
||||
West(Default::default(), self, other)
|
||||
fn to_west <A: Render<E>, B: Render<E>> (a: A, b: B) -> ToWest<E, A, B> {
|
||||
ToWest(None, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Render widget if predicate is true
|
||||
pub struct If<E: Engine, A: Render<E>>(PhantomData<E>, bool, A);
|
||||
|
||||
impl<E: Engine, A: Render<E>> Content<E> for If<E, A> {
|
||||
fn content (&self) -> impl Render<E> {
|
||||
if self.1 { Some(widget(&self.2)) } else { None }
|
||||
pub trait LayoutBspFixedStatic<E: Engine>: {
|
||||
fn to_north <A: Render<E>, B: Render<E>> (n: E::Unit, a: A, b: B) -> ToNorth<E, A, B> {
|
||||
ToNorth(Some(n), a, b)
|
||||
}
|
||||
fn to_south <A: Render<E>, B: Render<E>> (n: E::Unit, a: A, b: B) -> ToSouth<E, A, B> {
|
||||
ToSouth(Some(n), a, b)
|
||||
}
|
||||
fn to_east <A: Render<E>, B: Render<E>> (n: E::Unit, a: A, b: B) -> ToEast<E, A, B> {
|
||||
ToEast(Some(n), a, b)
|
||||
}
|
||||
fn to_west <A: Render<E>, B: Render<E>> (n: E::Unit, a: A, b: B) -> ToWest<E, A, B> {
|
||||
ToWest(Some(n), a, b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Render widget A if predicate is true, otherwise widget B
|
||||
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, bool, A, B);
|
||||
|
||||
pub struct Over<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, A, B);
|
||||
|
||||
pub struct Under<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, A, B);
|
||||
|
||||
pub struct North<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, A, B);
|
||||
pub struct ToNorth<E: Engine, A: Render<E>, B: Render<E>>(Option<E::Unit>, A, B);
|
||||
|
||||
pub struct South<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, A, B);
|
||||
pub struct ToSouth<E: Engine, A: Render<E>, B: Render<E>>(Option<E::Unit>, A, B);
|
||||
|
||||
pub struct East<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, A, B);
|
||||
pub struct ToEast<E: Engine, A: Render<E>, B: Render<E>>(Option<E::Unit>, A, B);
|
||||
|
||||
pub struct West<E: Engine, A: Render<E>, B: Render<E>>(PhantomData<E>, A, B);
|
||||
pub struct ToWest<E: Engine, A: Render<E>, B: Render<E>>(Option<E::Unit>, A, B);
|
||||
|
||||
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for ToNorth<E, A, B> {
|
||||
fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
||||
todo!();
|
||||
}
|
||||
fn render (&self, _: &mut E::Output) -> Usually<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for ToSouth<E, A, B> {
|
||||
fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
||||
todo!();
|
||||
}
|
||||
fn render (&self, _: &mut E::Output) -> Usually<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for ToEast<E, A, B> {
|
||||
fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
||||
todo!();
|
||||
}
|
||||
fn render (&self, _: &mut E::Output) -> Usually<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
67
crates/tek_layout/src/cond.rs
Normal file
67
crates/tek_layout/src/cond.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, R: Render<E>> LayoutCond<E> for R {}
|
||||
|
||||
pub trait LayoutCond<E: Engine>: Render<E> + Sized {
|
||||
fn when (self, cond: bool) -> If<E, Self> {
|
||||
If(Default::default(), cond, self)
|
||||
}
|
||||
fn or <B: Render<E>> (self, cond: bool, other: B) -> Either<E, Self, B> {
|
||||
Either(Default::default(), cond, self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> LayoutCondStatic<E> for E {}
|
||||
|
||||
pub trait LayoutCondStatic<E: Engine> {
|
||||
fn either <A: Render<E>, B: Render<E>> (
|
||||
condition: bool,
|
||||
a: A,
|
||||
b: B,
|
||||
) -> Either<E, A, B> {
|
||||
Either(Default::default(), condition, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Render widget if predicate is true
|
||||
pub struct If<E: Engine, A: Render<E>>(PhantomData<E>, bool, A);
|
||||
|
||||
impl<E: Engine, A: Render<E>> Render<E> for If<E, A> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
if self.1 {
|
||||
return self.2.min_size(to)
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
if self.1 {
|
||||
return self.2.render(to)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Render widget A if predicate is true, otherwise widget B
|
||||
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(
|
||||
PhantomData<E>,
|
||||
bool,
|
||||
A,
|
||||
B,
|
||||
);
|
||||
|
||||
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Either<E, A, B> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
if self.1 {
|
||||
return self.2.min_size(to)
|
||||
} else {
|
||||
return self.3.min_size(to)
|
||||
}
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
if self.1 {
|
||||
return self.2.render(to)
|
||||
} else {
|
||||
return self.3.render(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutFill<E> for W {}
|
||||
impl<E: Engine> LayoutFill<E> for E {}
|
||||
|
||||
pub trait LayoutFill<E: Engine>: Render<E> + Sized {
|
||||
fn fill_x (self) -> Fill<E, Self> {
|
||||
Fill::X(self)
|
||||
pub trait LayoutFill<E: Engine> {
|
||||
fn fill_x <W: Render<E>> (fill: W) -> Fill<E, W> {
|
||||
Fill::X(fill)
|
||||
}
|
||||
fn fill_y (self) -> Fill<E, Self> {
|
||||
Fill::Y(self)
|
||||
fn fill_y <W: Render<E>> (fill: W) -> Fill<E, W> {
|
||||
Fill::Y(fill)
|
||||
}
|
||||
fn fill_xy (self) -> Fill<E, Self> {
|
||||
Fill::XY(self)
|
||||
fn fill_xy <W: Render<E>> (fill: W) -> Fill<E, W> {
|
||||
Fill::XY(fill)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutGrow<E> for W {}
|
||||
|
||||
pub trait LayoutGrow<E: Engine>: Render<E> + Sized {
|
||||
fn grow_x (self, x: E::Unit) -> Grow<E::Unit, Self> {
|
||||
Grow::X(x, self)
|
||||
}
|
||||
fn grow_y (self, y: E::Unit) -> Grow<E::Unit, Self> {
|
||||
Grow::Y(y, self)
|
||||
}
|
||||
fn grow_xy (self, x: E::Unit, y: E::Unit) -> Grow<E::Unit, Self> {
|
||||
Grow::XY(x, y, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand drawing area
|
||||
pub enum Grow<N: Coordinate, T> {
|
||||
/// Increase width
|
||||
X(N, T),
|
||||
/// Increase height
|
||||
Y(N, T),
|
||||
/// Increase width and height
|
||||
XY(N, N, T)
|
||||
}
|
||||
|
||||
impl<N: Coordinate, T> Grow<N, T> {
|
||||
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 Grow<E::Unit, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() + w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() + h],
|
||||
Self::XY(w, h, _) => [to.w() + w, to.h() + h],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutInset<E> for W {}
|
||||
|
||||
pub trait LayoutInset<E: Engine>: Render<E> + Sized {
|
||||
fn inset_x (self, x: E::Unit) -> Inset<E, Self> {
|
||||
Inset::X(x, self)
|
||||
}
|
||||
fn inset_y (self, y: E::Unit) -> Inset<E, Self> {
|
||||
Inset::Y(y, self)
|
||||
}
|
||||
fn inset_xy (self, x: E::Unit, y: E::Unit) -> Inset<E, Self> {
|
||||
Inset::XY(x, y, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink from each side
|
||||
pub enum Inset<E: Engine, T> {
|
||||
_Unused(PhantomData<E>),
|
||||
/// 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 {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, ref inner) => (inner as &dyn Render<E>).shrink_x(x).push_x(x),
|
||||
Self::Y(y, ref inner) => (inner as &dyn Render<E>).shrink_y(y).push_y(y),
|
||||
Self::XY(x, y, ref inner) => (inner as &dyn Render<E>).shrink_xy(x, y).push_xy(x, y),
|
||||
_ => unreachable!(),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
99
crates/tek_layout/src/inset_outset.rs
Normal file
99
crates/tek_layout/src/inset_outset.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
use crate::*;
|
||||
|
||||
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> {
|
||||
_Unused(PhantomData<E>),
|
||||
/// 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 {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)),
|
||||
_ => unreachable!(),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
||||
/// Grow on each side
|
||||
pub enum Outset<E: Engine, T: Render<E>> {
|
||||
_Unused(PhantomData<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 {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
_ => unreachable!(),
|
||||
}.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),
|
||||
_ => unreachable!(),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ where
|
|||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
if let Some(size) = self.min_size(to.area().wh().into())? {
|
||||
(self.0)(&mut |layer|to.render_in(to.area().clip(size).into(), &layer))
|
||||
(self.0)(&mut |layer|to.render_in(to.area().clip(size).into(), layer))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,52 +3,22 @@ pub(crate) use tek_core::*;
|
|||
submod! {
|
||||
align
|
||||
bsp
|
||||
cond
|
||||
debug
|
||||
fill
|
||||
fixed
|
||||
grow
|
||||
inset
|
||||
inset_outset
|
||||
layers
|
||||
max
|
||||
map_reduce
|
||||
measure
|
||||
min
|
||||
outset
|
||||
pull
|
||||
push
|
||||
min_max
|
||||
push_pull
|
||||
scroll
|
||||
shrink
|
||||
shrink_grow
|
||||
split
|
||||
stack
|
||||
//stack
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! lay {
|
||||
($($expr:expr),* $(,)?) => { Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) }
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! col {
|
||||
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
|
||||
($pat:pat in $collection:expr => $item:expr) => {
|
||||
Stack::down(move |add|{
|
||||
for $pat in $collection { add(&$item)?; }
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
#[macro_export] macro_rules! col_up {
|
||||
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
|
||||
($pat:pat in $collection:expr => $item:expr) => {
|
||||
Stack::up(move |add|{
|
||||
for $pat in $collection { add(&$item)?; }
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
#[macro_export] macro_rules! row {
|
||||
($($expr:expr),* $(,)?) => { Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
|
||||
($pat:pat in $collection:expr => $item:expr) => {
|
||||
Stack::right(move |add|{
|
||||
for $pat in $collection { add(&$item)?; }
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
crates/tek_layout/src/map_reduce.rs
Normal file
34
crates/tek_layout/src/map_reduce.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine> LayoutMapReduce<E> for E {}
|
||||
|
||||
pub trait LayoutMapReduce<E: Engine> {
|
||||
fn map <T, I, R, F> (iterator: I, callback: F) -> Map<E, T, I, R, F>
|
||||
where
|
||||
I: Iterator<Item=T>,
|
||||
R: Render<E>,
|
||||
F: Fn(T)->R
|
||||
{
|
||||
Map(Default::default(), iterator, callback)
|
||||
}
|
||||
fn reduce <T, I, R, F> (iterator: I, callback: F) -> Reduce<E, T, I, R, F>
|
||||
where
|
||||
I: Iterator<Item=T>,
|
||||
R: Render<E>,
|
||||
F: Fn(R, T)->R
|
||||
{
|
||||
Reduce(Default::default(), iterator, callback)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Map<E: Engine, T, I: Iterator<Item=T>, R: Render<E>, F: Fn(T)->R>(
|
||||
PhantomData<E>,
|
||||
I,
|
||||
F
|
||||
);
|
||||
|
||||
pub struct Reduce<E: Engine, T, I: Iterator<Item=T>, R: Render<E>, F: Fn(R, T)->R>(
|
||||
PhantomData<(E, R)>,
|
||||
I,
|
||||
F
|
||||
);
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutMax<E> for W {}
|
||||
|
||||
pub trait LayoutMax<E: Engine>: Render<E> + Sized {
|
||||
fn max_x (self, x: E::Unit) -> Max<E::Unit, Self> { Max::X(x, self) }
|
||||
fn max_y (self, y: E::Unit) -> Max<E::Unit, Self> { Max::Y(y, self) }
|
||||
fn max_xy (self, x: E::Unit, y: E::Unit) -> Max<E::Unit, Self> { Max::XY(x, y, self) }
|
||||
}
|
||||
|
||||
/// Enforce maximum size of drawing area
|
||||
pub enum Max<U: Coordinate, T> {
|
||||
/// Enforce maximum width
|
||||
X(U, T),
|
||||
/// Enforce maximum height
|
||||
Y(U, T),
|
||||
/// Enforce maximum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
|
||||
impl<N: Coordinate, T> Max<N, T> {
|
||||
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 Max<E:: Unit, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().min(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().min(h)],
|
||||
Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutMin<E> for W {}
|
||||
|
||||
pub trait LayoutMin<E: Engine>: Render<E> + Sized {
|
||||
fn min_x (self, x: E::Unit) -> Min<E::Unit, Self> { Min::X(x, self) }
|
||||
fn min_y (self, y: E::Unit) -> Min<E::Unit, Self> { Min::Y(y, self) }
|
||||
fn min_xy (self, x: E::Unit, y: E::Unit) -> Min<E::Unit, Self> { Min::XY(x, y, self) }
|
||||
}
|
||||
|
||||
/// Enforce minimum size of drawing area
|
||||
pub enum Min<U: Coordinate, T> {
|
||||
/// Enforce minimum width
|
||||
X(U, T),
|
||||
/// Enforce minimum height
|
||||
Y(U, T),
|
||||
/// Enforce minimum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
impl<N: Coordinate, T> Min<N, 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 Min<E::Unit, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().max(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().max(h)],
|
||||
Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)],
|
||||
}.into()))
|
||||
}
|
||||
// TODO: 🡘 🡙 ←🡙→
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
85
crates/tek_layout/src/min_max.rs
Normal file
85
crates/tek_layout/src/min_max.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine> LayoutMinMax<E> for E {}
|
||||
|
||||
pub trait LayoutMinMax<E: Engine> {
|
||||
fn min_x <W: Render<E>> (x: E::Unit, w: W) -> Min<E::Unit, W> {
|
||||
Min::X(x, w)
|
||||
}
|
||||
fn min_y <W: Render<E>> (y: E::Unit, w: W) -> Min<E::Unit, W> {
|
||||
Min::Y(y, w)
|
||||
}
|
||||
fn min_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Min<E::Unit, W> {
|
||||
Min::XY(x, y, w)
|
||||
}
|
||||
fn max_x <W: Render<E>> (x: E::Unit, w: W) -> Max<E::Unit, W> {
|
||||
Max::X(x, w)
|
||||
}
|
||||
fn max_y <W: Render<E>> (y: E::Unit, w: W) -> Max<E::Unit, W> {
|
||||
Max::Y(y, w)
|
||||
}
|
||||
fn max_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Max<E::Unit, W> {
|
||||
Max::XY(x, y, w)
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce minimum size of drawing area
|
||||
pub enum Min<U: Coordinate, T> {
|
||||
/// Enforce minimum width
|
||||
X(U, T),
|
||||
/// Enforce minimum height
|
||||
Y(U, T),
|
||||
/// Enforce minimum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
impl<N: Coordinate, T> Min<N, 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 Min<E::Unit, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().max(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().max(h)],
|
||||
Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)],
|
||||
}.into()))
|
||||
}
|
||||
// TODO: 🡘 🡙 ←🡙→
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce maximum size of drawing area
|
||||
pub enum Max<U: Coordinate, T> {
|
||||
/// Enforce maximum width
|
||||
X(U, T),
|
||||
/// Enforce maximum height
|
||||
Y(U, T),
|
||||
/// Enforce maximum width and height
|
||||
XY(U, U, T),
|
||||
}
|
||||
|
||||
impl<N: Coordinate, T> Max<N, T> {
|
||||
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 Max<E:: Unit, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().min(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().min(h)],
|
||||
Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutOutset<E> for W {}
|
||||
|
||||
pub trait LayoutOutset<E: Engine>: Render<E> + Sized {
|
||||
fn outset_x (self, x: E::Unit) -> Outset<E, Self> {
|
||||
Outset::X(x, self)
|
||||
}
|
||||
fn outset_y (self, y: E::Unit) -> Outset<E, Self> {
|
||||
Outset::Y(y, self)
|
||||
}
|
||||
fn outset_xy (self, x: E::Unit, y: E::Unit) -> Outset<E, Self> {
|
||||
Outset::XY(x, y, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Grow on each side
|
||||
pub enum Outset<E: Engine, T: Render<E>> {
|
||||
_Unused(PhantomData<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 {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) => (inner as &dyn Render<E>).grow_x(x + x),
|
||||
Self::Y(y, ref inner) => (inner as &dyn Render<E>).grow_y(y + y),
|
||||
Self::XY(x, y, ref inner) => (inner as &dyn Render<E>).grow_xy(x + x, y + y),
|
||||
_ => unreachable!(),
|
||||
}.min_size(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
match *self {
|
||||
Self::X(x, ref inner) => (inner as &dyn Render<E>).push_x(x),
|
||||
Self::Y(y, ref inner) => (inner as &dyn Render<E>).push_y(y),
|
||||
Self::XY(x, y, ref inner) => (inner as &dyn Render<E>).push_xy(x, y),
|
||||
_ => unreachable!(),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutPull<E> for W {}
|
||||
|
||||
pub trait LayoutPull<E: Engine>: Render<E> + Sized {
|
||||
fn pull_x (self, x: E::Unit) -> Pull<E, Self> {
|
||||
Pull::X(x, self)
|
||||
}
|
||||
fn pull_y (self, y: E::Unit) -> Pull<E, Self> {
|
||||
Pull::Y(y, self)
|
||||
}
|
||||
fn pull_xy (self, x: E::Unit, y: E::Unit) -> Pull<E, Self> {
|
||||
Pull::XY(x, y, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Move 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 {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn x (&self) -> E::Unit {
|
||||
match self {
|
||||
Self::X(x, _) => *x,
|
||||
Self::Y(_, _) => E::Unit::default(),
|
||||
Self::XY(x, _, _) => *x,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn y (&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(()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutPush<E> for W {}
|
||||
|
||||
pub trait LayoutPush<E: Engine>: Render<E> + Sized {
|
||||
fn push_x (self, x: E::Unit) -> Push<E, Self> {
|
||||
Push::X(x, self)
|
||||
}
|
||||
fn push_y (self, y: E::Unit) -> Push<E, Self> {
|
||||
Push::Y(y, self)
|
||||
}
|
||||
fn push_xy (self, x: E::Unit, y: E::Unit) -> Push<E, Self> {
|
||||
Push::XY(x, y, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Move 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),
|
||||
}
|
||||
|
||||
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,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn x (&self) -> E::Unit {
|
||||
match self {
|
||||
Self::X(x, _) => *x,
|
||||
Self::Y(_, _) => E::Unit::default(),
|
||||
Self::XY(x, _, _) => *x,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn y (&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 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()],
|
||||
_ => unreachable!(),
|
||||
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
132
crates/tek_layout/src/push_pull.rs
Normal file
132
crates/tek_layout/src/push_pull.rs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
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),
|
||||
}
|
||||
|
||||
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,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn x (&self) -> E::Unit {
|
||||
match self {
|
||||
Self::X(x, _) => *x,
|
||||
Self::Y(_, _) => E::Unit::default(),
|
||||
Self::XY(x, _, _) => *x,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn y (&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 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()],
|
||||
_ => unreachable!(),
|
||||
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn x (&self) -> E::Unit {
|
||||
match self {
|
||||
Self::X(x, _) => *x,
|
||||
Self::Y(_, _) => E::Unit::default(),
|
||||
Self::XY(x, _, _) => *x,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn y (&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(()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, W: Render<E>> LayoutShrink<E> for W {}
|
||||
|
||||
pub trait LayoutShrink<E: Engine>: Render<E> + Sized {
|
||||
fn shrink_x (self, x: E::Unit) -> Shrink<E, Self> {
|
||||
Shrink::X(x, self)
|
||||
}
|
||||
fn shrink_y (self, y: E::Unit) -> Shrink<E, Self> {
|
||||
Shrink::Y(y, self)
|
||||
}
|
||||
fn shrink_xy (self, x: E::Unit, y: E::Unit) -> Shrink<E, Self> {
|
||||
Shrink::XY(x, y, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink drawing area
|
||||
pub enum Shrink<E: Engine, T> {
|
||||
_Unused(PhantomData<E>),
|
||||
/// 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>> Shrink<E, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Shrink<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [
|
||||
if to.w() > w { to.w() - w } else { 0.into() },
|
||||
to.h()
|
||||
],
|
||||
Self::Y(h, _) => [
|
||||
to.w(),
|
||||
if to.h() > h { to.h() - h } else { 0.into() }
|
||||
],
|
||||
Self::XY(w, h, _) => [
|
||||
if to.w() > w { to.w() - w } else { 0.into() },
|
||||
if to.h() > h { to.h() - h } else { 0.into() }
|
||||
],
|
||||
_ => unreachable!(),
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
102
crates/tek_layout/src/shrink_grow.rs
Normal file
102
crates/tek_layout/src/shrink_grow.rs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine> LayoutShrinkGrow<E> for E {}
|
||||
|
||||
pub trait LayoutShrinkGrow<E: Engine> {
|
||||
fn shrink_x <W: Render<E>> (x: E::Unit, w: W) -> Shrink<E, W> {
|
||||
Shrink::X(x, w)
|
||||
}
|
||||
fn shrink_y <W: Render<E>> (y: E::Unit, w: W) -> Shrink<E, W> {
|
||||
Shrink::Y(y, w)
|
||||
}
|
||||
fn shrink_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Shrink<E, W> {
|
||||
Shrink::XY(x, y, w)
|
||||
}
|
||||
fn grow_x <W: Render<E>> (x: E::Unit, w: W) -> Grow<E::Unit, W> {
|
||||
Grow::X(x, w)
|
||||
}
|
||||
fn grow_y <W: Render<E>> (y: E::Unit, w: W) -> Grow<E::Unit, W> {
|
||||
Grow::Y(y, w)
|
||||
}
|
||||
fn grow_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Grow<E::Unit, W> {
|
||||
Grow::XY(x, y, w)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink drawing area
|
||||
pub enum Shrink<E: Engine, T> {
|
||||
_Unused(PhantomData<E>),
|
||||
/// 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>> Shrink<E, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Shrink<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [
|
||||
if to.w() > w { to.w() - w } else { 0.into() },
|
||||
to.h()
|
||||
],
|
||||
Self::Y(h, _) => [
|
||||
to.w(),
|
||||
if to.h() > h { to.h() - h } else { 0.into() }
|
||||
],
|
||||
Self::XY(w, h, _) => [
|
||||
if to.w() > w { to.w() - w } else { 0.into() },
|
||||
if to.h() > h { to.h() - h } else { 0.into() }
|
||||
],
|
||||
_ => unreachable!(),
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand drawing area
|
||||
pub enum Grow<N: Coordinate, T> {
|
||||
/// Increase width
|
||||
X(N, T),
|
||||
/// Increase height
|
||||
Y(N, T),
|
||||
/// Increase width and height
|
||||
XY(N, N, T)
|
||||
}
|
||||
|
||||
impl<N: Coordinate, T> Grow<N, T> {
|
||||
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 Grow<E::Unit, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() + w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() + h],
|
||||
Self::XY(w, h, _) => [to.w() + w, to.h() + h],
|
||||
}.into()))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||
.transpose()?.unwrap_or(()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,33 @@
|
|||
use crate::*;
|
||||
|
||||
#[macro_export] macro_rules! col {
|
||||
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
|
||||
($pat:pat in $collection:expr => $item:expr) => {
|
||||
Stack::down(move |add|{
|
||||
for $pat in $collection { add(&$item)?; }
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
#[macro_export] macro_rules! col_up {
|
||||
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
|
||||
($pat:pat in $collection:expr => $item:expr) => {
|
||||
Stack::up(move |add|{
|
||||
for $pat in $collection { add(&$item)?; }
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
#[macro_export] macro_rules! row {
|
||||
($($expr:expr),* $(,)?) => { Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
|
||||
($pat:pat in $collection:expr => $item:expr) => {
|
||||
Stack::right(move |add|{
|
||||
for $pat in $collection { add(&$item)?; }
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Stack<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||
|
|
@ -36,7 +64,7 @@ where
|
|||
(self.0)(&mut |component: &dyn Render<E>| {
|
||||
let max = to.h().minus(h);
|
||||
if max > E::Unit::ZERO() {
|
||||
let item = component.push_y(h).max_y(max);
|
||||
let item = E::max_y(max, E::push_y(h, component));
|
||||
let size = item.min_size(to)?.map(|size|size.wh());
|
||||
if let Some([width, height]) = size {
|
||||
h = h + height.into();
|
||||
|
|
@ -54,7 +82,7 @@ where
|
|||
(self.0)(&mut |component: &dyn Render<E>| {
|
||||
let max = to.w().minus(w);
|
||||
if max > E::Unit::ZERO() {
|
||||
let item = component.push_x(w).max_x(max);
|
||||
let item = E::max_x(max, E::push_x(h, component));
|
||||
let size = item.min_size(to)?.map(|size|size.wh());
|
||||
if let Some([width, height]) = size {
|
||||
w = w + width.into();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue