wip: refactor(output): 91 more errors...

This commit is contained in:
same mf who else 2026-02-14 20:14:27 +02:00
parent eaa05b7f09
commit f033f9ff54
5 changed files with 247 additions and 230 deletions

View file

@ -16,14 +16,150 @@ pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}
pub(crate) use std::marker::PhantomData; pub(crate) use std::marker::PhantomData;
pub(crate) use dizzle::*; pub(crate) use dizzle::*;
mod out_macros; // Must be defined first // Define macros first, so that private macros are available in private modules.
/// Clear a pre-allocated buffer, then write into it.
#[macro_export] macro_rules! rewrite {
($buf:ident, $($rest:tt)*) => { |$buf,_,_|{ $buf.clear(); write!($buf, $($rest)*) } }
}
/// FIXME: This macro should be some variant of `eval`, too.
/// But taking into account the different signatures (resolving them into 1?)
#[cfg(feature = "dsl")] #[macro_export] macro_rules! draw {
($State:ident: $Output:ident: $layers:expr) => {
impl Draw<$Output> for $State {
fn draw (&self, to: &mut $Output) {
for layer in $layers { layer(self, to) }
}
}
}
}
/// FIXME: This is generic: should be called `eval` and be part of [dizzle].
#[cfg(feature = "dsl")] #[macro_export] macro_rules! view {
($State:ident: $Output:ident: $namespaces:expr) => {
impl View<$Output, ()> for $State {
fn view_expr <'a> (&'a self, to: &mut $Output, expr: &'a impl Expression) -> Usually<()> {
for namespace in $namespaces { if namespace(self, to, expr)? { return Ok(()) } }
Err(format!("{}::<{}, ()>::view_expr: unexpected: {expr:?}",
stringify! { $State },
stringify! { $Output }).into())
}
}
}
}
/// Stack things on top of each other,
#[macro_export] macro_rules! lay (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::b(bsp, $expr);)*; bsp }});
/// Stack southward.
#[macro_export] macro_rules! col (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::s(bsp, $expr);)*; bsp }});
/// Stack northward.
#[macro_export] macro_rules! col_up (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::n(bsp, $expr);)*; bsp }});
/// Stack eastward.
#[macro_export] macro_rules! row (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::e(bsp, $expr);)*; bsp }});
/// Define layout operation.
macro_rules! layout_op_xy (
// Variant for layout ops that take no coordinates
(0: $T: ident) => {
impl<A> $T<A> {
#[inline] pub const fn inner (&self) -> &A {
match self { Self::X(c) | Self::Y(c) | Self::XY(c) => c }
}
}
impl<O: Out, T: Content<O>> Draw<O> for $T<T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
}
};
// Variant for layout ops that take one coordinate
(1: $T: ident) => {
impl<U, A> $T<U, A> {
#[inline] pub const fn inner (&self) -> &A {
match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c, }
}
}
impl<O: Out, T: Content<O>> Draw<O> for $T<O::Unit, T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
}
impl<U: Coord, A> $T<U, A> {
#[inline] pub fn dx (&self) -> U {
match self { Self::X(x, _) | Self::XY(x, ..) => *x, _ => 0.into() }
}
#[inline] pub fn dy (&self) -> U {
match self { Self::Y(y, _) | Self::XY(y, ..) => *y, _ => 0.into() }
}
}
};
(1 opt: $T: ident) => {
impl<U, A> $T<U, A> {
#[inline] pub const fn inner (&self) -> &A {
match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c, }
}
}
impl<O: Out, T: Content<O>> Draw<O> for $T<O::Unit, T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
}
impl<U: Coord, A> $T<U, A> {
#[inline] pub const fn dx (&self) -> Option<U> {
match self { Self::X(x, _) | Self::XY(x, ..) => Some(*x), _ => None }
}
#[inline] pub const fn dy (&self) -> Option<U> {
match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None }
}
}
};
);
// Implement layout op that increments X and/or Y by fixed amount.
macro_rules! push_pull(($T:ident: $method: ident)=>{
layout_op_xy!(1: $T);
impl<O: Out, T: Layout<O>> Layout<O> for $T<O::Unit, T> {
fn x (&self, area: O::Area) -> O::Unit { area.x().$method(self.dx()) }
fn y (&self, area: O::Area) -> O::Unit { area.y().$method(self.dy()) }
}
});
macro_rules! impl_map_direction (($name:ident, $axis:ident, $align:ident)=>{
impl<'a, O, A, B, I, F> Map<
O, A, Push<O::Unit, Align<Fixed<O::Unit, Fill<B>>>>, I, F, fn(A, usize)->B
> where
O: Out,
B: Draw<O>,
I: Iterator<Item = A> + Send + Sync + 'a,
F: Fn() -> I + Send + Sync + 'a
{
pub const fn $name (
size: O::Unit,
get_iter: F,
get_item: impl Fn(A, usize)->B + Send + Sync
) -> Map<
O, A,
Push<O::Unit, Align<Fixed<O::Unit, B>>>,
I, F,
impl Fn(A, usize)->Push<O::Unit, Align<Fixed<O::Unit, B>>> + Send + Sync
> {
Map {
__: PhantomData,
get_iter,
get_item: move |item: A, index: usize|{
// FIXME: multiply
let mut push: O::Unit = O::Unit::from(0u16);
for _ in 0..index {
push = push + size;
}
Push::$axis(push, Align::$align(Fixed::$axis(size, get_item(item, index))))
}
}
}
}
});
mod out_traits; pub use self::out_traits::*; mod out_traits; pub use self::out_traits::*;
mod out_structs; pub use self::out_structs::*; mod out_structs; pub use self::out_structs::*;
mod out_impls; pub use self::out_impls::*; mod out_impls; pub use self::out_impls::*;
mod widget; pub use self::widget::*;
mod layout; pub use self::layout::*;
#[cfg(test)] mod out_tests; #[cfg(test)] mod out_tests;
#[cfg(feature = "dsl")] #[cfg(feature = "dsl")]

View file

@ -1,4 +1,6 @@
use crate::*; use crate::*;
use Direction::*;
use Alignment::*;
impl Coord for u16 { impl Coord for u16 {
fn plus (self, other: Self) -> Self { self.saturating_add(other) } fn plus (self, other: Self) -> Self { self.saturating_add(other) }
@ -9,11 +11,35 @@ impl<N: Coord> HasXY<N> for XY<N> {
fn y (&self) -> N { self.1 } fn y (&self) -> N { self.1 }
} }
impl<N: Coord> HasXY<N> for XYWH<N> {
fn x (&self) -> N { self.0 }
fn y (&self) -> N { self.1 }
}
impl<O: Out> HasXY<O::Unit> for O {
// X coordinate of output area
#[inline] fn x (&self) -> O::Unit { self.area().x() }
// Y coordinate of output area
#[inline] fn y (&self) -> O::Unit { self.area().y() }
}
impl<N: Coord> HasWH<N> for WH<N> { impl<N: Coord> HasWH<N> for WH<N> {
fn w (&self) -> N { self.0 } fn w (&self) -> N { self.0 }
fn h (&self) -> N { self.1 } fn h (&self) -> N { self.1 }
} }
impl<N: Coord> HasWH<N> for XYWH<N> {
fn w (&self) -> N { self.2 }
fn h (&self) -> N { self.3 }
}
impl<O: Out> HasWH<O::Unit> for O {
// Width of output area
#[inline] fn w (&self) -> O::Unit { self.area().w() }
// Height of output area
#[inline] fn h (&self) -> O::Unit { self.area().h() }
}
impl<N: Coord> WH<N> { impl<N: Coord> WH<N> {
fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w), self.h()] } fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w), self.h()] }
fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h)] } fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h)] }
@ -24,48 +50,49 @@ impl<N: Coord> WH<N> {
Ok(self) Ok(self)
} }
} }
impl<N: Coord> XYWH<N> { impl<N: Coord> XYWH<N> {
fn from_position (pos: impl Size<N>) -> Self { /// Iterate over every covered X coordinate.
let [x, y] = pos.wh();
[x, y, 0.into(), 0.into()]
}
fn from_size (size: impl Size<N>) -> Self {
let [w, h] = size.wh();
[0.into(), 0.into(), w, h]
}
fn lrtb (&self) -> [N;4] {
[self.x(), self.x2(), self.y(), self.y2()]
}
fn center (&self) -> XY<N> {
[self.x().plus(self.w()/2.into()), self.y().plus(self.h()/2.into())]
}
fn centered (&self) -> XY<N> {
[self.x().minus(self.w()/2.into()), self.y().minus(self.h()/2.into())]
}
fn centered_x (&self, n: N) -> XYWH<N> {
let [x, y, w, h] = self.xywh();
[(x.plus(w / 2.into())).minus(n / 2.into()), y.plus(h / 2.into()), n, 1.into()]
}
fn centered_y (&self, n: N) -> XYWH<N> {
let [x, y, w, h] = self.xywh();
[x.plus(w / 2.into()), (y.plus(h / 2.into())).minus(n / 2.into()), 1.into(), n]
}
fn centered_xy (&self, [n, m]: [N;2]) -> XYWH<N> {
let [x, y, w, h] = self.xywh();
[(x.plus(w / 2.into())).minus(n / 2.into()), (y.plus(h / 2.into())).minus(m / 2.into()), n, m]
}
fn iter_x (&self) -> impl Iterator<Item = N> where N: std::iter::Step { fn iter_x (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
self.x()..(self.x()+self.w()) self.x()..(self.x()+self.w())
} }
/// Iterate over every covered Y coordinate.
fn iter_y (&self) -> impl Iterator<Item = N> where N: std::iter::Step { fn iter_y (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
self.y()..(self.y()+self.h()) self.y()..(self.y()+self.h())
} }
fn clipped (&self, wh: impl Size<N>) -> XYWH<N> { fn from_position (pos: impl HasWH<N>) -> Self {
[self.x(), self.y(), wh.w(), wh.h()] let [x, y] = pos.wh();
Self(x, y, 0.into(), 0.into())
}
fn from_size (size: impl HasWH<N>) -> Self {
let [w, h] = size.wh();
Self(0.into(), 0.into(), w, h)
}
fn lrtb (&self) -> [N;4] {
Self(self.x(), self.x2(), self.y(), self.y2())
}
fn center (&self) -> XY<N> {
Self(self.x().plus(self.w()/2.into()), self.y().plus(self.h()/2.into()))
}
fn centered (&self) -> XY<N> {
Self(self.x().minus(self.w()/2.into()), self.y().minus(self.h()/2.into()))
}
fn centered_x (&self, n: N) -> XYWH<N> {
let [x, y, w, h] = self.xywh();
Self((x.plus(w / 2.into())).minus(n / 2.into()), y.plus(h / 2.into()), n, 1.into())
}
fn centered_y (&self, n: N) -> XYWH<N> {
let [x, y, w, h] = self.xywh();
Self(x.plus(w / 2.into()), (y.plus(h / 2.into())).minus(n / 2.into()), 1.into(), n)
}
fn centered_xy (&self, [n, m]: [N;2]) -> XYWH<N> {
let [x, y, w, h] = self.xywh();
Self((x.plus(w / 2.into())).minus(n / 2.into()), (y.plus(h / 2.into())).minus(m / 2.into()), n, m)
}
fn clipped (&self, wh: impl HasWH<N>) -> XYWH<N> {
Self(self.x(), self.y(), wh.w(), wh.h())
} }
fn clipped_h (&self, h: N) -> XYWH<N> { fn clipped_h (&self, h: N) -> XYWH<N> {
[self.x(), self.y(), self.w(), self.h().min(h)] Self(self.x(), self.y(), self.w(), self.h().min(h))
} }
fn clipped_w (&self, w: N) -> XYWH<N> { fn clipped_w (&self, w: N) -> XYWH<N> {
[self.x(), self.y(), self.w().min(w), self.h()] [self.x(), self.y(), self.w().min(w), self.h()]
@ -77,31 +104,6 @@ impl<N: Coord> XYWH<N> {
[self.x(), self.y(), self.w(), h] [self.x(), self.y(), self.w(), h]
} }
} }
impl<N: Coord> HasXY<N> for XYWH<N> {
fn x (&self) -> N { self.0 }
fn y (&self) -> N { self.1 }
}
impl<N: Coord> HasWH<N> for XYWH<N> {
fn w (&self) -> N { self.2 }
fn h (&self) -> N { self.3 }
}
impl<O: Out> super::ng::HasXY<O::Unit> for O {
// X coordinate of output area
#[inline] fn x (&self) -> O::Unit { self.area().x() }
// Y coordinate of output area
#[inline] fn y (&self) -> O::Unit { self.area().y() }
}
impl<O: Out> super::ng::HasWH<O::Unit> for O {
// Width of output area
#[inline] fn w (&self) -> O::Unit { self.area().w() }
// Height of output area
#[inline] fn h (&self) -> O::Unit { self.area().h() }
}
impl<O: Out, T: Draw<O> + Layout<O>> Content<O> for T {} impl<O: Out, T: Draw<O> + Layout<O>> Content<O> for T {}
impl<'a, O: Out> AsRef<dyn Draw<O> + 'a> for dyn Content<O> + 'a { impl<'a, O: Out> AsRef<dyn Draw<O> + 'a> for dyn Content<O> + 'a {
@ -190,8 +192,8 @@ impl<T: PartialEq, U> Memo<T, U> {
} }
impl Direction { impl Direction {
pub fn split_fixed <N: Coord> (self, area: impl Area<N>, a: N) -> ([N;4],[N;4]) { pub fn split_fixed <N: Coord> (self, area: impl HasXYWH<N>, a: N) -> ([N;4],[N;4]) {
let [x, y, w, h] = area.xywh(); let XYWH(x, y, w, h) = area.xywh();
match self { match self {
North => ([x, y.plus(h).minus(a), w, a], [x, y, w, h.minus(a)]), North => ([x, y.plus(h).minus(a), w, a], [x, y, w, h.minus(a)]),
South => ([x, y, w, a], [x, y.plus(a), w, h.minus(a)]), South => ([x, y, w, a], [x, y.plus(a), w, h.minus(a)]),
@ -202,16 +204,6 @@ impl Direction {
} }
} }
impl<N: Coord> Size<N> for (N, N) {
fn x (&self) -> N { self.0 }
fn y (&self) -> N { self.1 }
}
impl<N: Coord> Size<N> for [N;2] {
fn x (&self) -> N { self[0] }
fn y (&self) -> N { self[1] }
}
impl<E: Out, T: Has<Measure<E>>> HasSize<E> for T { impl<E: Out, T: Has<Measure<E>>> HasSize<E> for T {
fn size (&self) -> &Measure<E> { fn size (&self) -> &Measure<E> {
self.get() self.get()
@ -513,11 +505,20 @@ impl<O: Out, T: Layout<O>> Layout<O> for Align<T> {
} }
impl<U, A> Pad<U, A> { impl<U, A> Pad<U, A> {
#[inline] pub const fn inner (&self) -> &A { match self { X(_, c) | Y(_, c) | XY(_, _, c) => c, } } #[inline] pub const fn inner (&self) -> &A {
use Pad::*;
match self { X(_, c) | Y(_, c) | XY(_, _, c) => c, }
}
} }
impl<U: Coord, T> Pad<U, T> { impl<U: Coord, T> Pad<U, T> {
#[inline] pub fn dx (&self) -> U { match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, } } #[inline] pub fn dx (&self) -> U {
#[inline] pub fn dy (&self) -> U { match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, } } use Pad::*;
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
}
#[inline] pub fn dy (&self) -> U {
use Pad::*;
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
}
} }
impl<O: Out, T: Content<O>> Draw<O> for Pad<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Pad<O::Unit, T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
@ -567,13 +568,27 @@ impl<O: Out, Head: Content<O>, Tail: Content<O>> Draw<O> for Bsp<Head, Tail> {
} }
} }
impl<O: Out, Head: Layout<O>, Tail: Layout<O>> Layout<O> for Bsp<Head, Tail> { impl<O: Out, Head: Layout<O>, Tail: Layout<O>> Layout<O> for Bsp<Head, Tail> {
fn w (&self, area: O::Area) -> O::Unit { match self.0 { Above | Below | North | South => self.1.w(area).max(self.2.w(area)), East | West => self.1.w_min(area).plus(self.2.w(area)), } } fn w (&self, area: O::Area) -> O::Unit {
fn w_min (&self, area: O::Area) -> O::Unit { match self.0 { Above | Below | North | South => self.1.w_min(area).max(self.2.w_min(area)), East | West => self.1.w_min(area).plus(self.2.w_min(area)), } } match self.0 { Above | Below | North | South => self.1.w(area).max(self.2.w(area)), East | West => self.1.w_min(area).plus(self.2.w(area)), }
fn w_max (&self, area: O::Area) -> O::Unit { match self.0 { Above | Below | North | South => self.1.w_max(area).max(self.2.w_max(area)), East | West => self.1.w_max(area).plus(self.2.w_max(area)), } } }
fn h (&self, area: O::Area) -> O::Unit { match self.0 { Above | Below | East | West => self.1.h(area).max(self.2.h(area)), North | South => self.1.h(area).plus(self.2.h(area)), } } fn w_min (&self, area: O::Area) -> O::Unit {
fn h_min (&self, area: O::Area) -> O::Unit { match self.0 { Above | Below | East | West => self.1.h_min(area).max(self.2.h_min(area)), North | South => self.1.h_min(area).plus(self.2.h_min(area)), } } match self.0 { Above | Below | North | South => self.1.w_min(area).max(self.2.w_min(area)), East | West => self.1.w_min(area).plus(self.2.w_min(area)), }
fn h_max (&self, area: O::Area) -> O::Unit { match self.0 { Above | Below | North | South => self.1.h_max(area).max(self.2.h_max(area)), East | West => self.1.h_max(area).plus(self.2.h_max(area)), } } }
fn layout (&self, area: O::Area) -> O::Area { bsp_areas(area, self.0, &self.1, &self.2)[2] } fn w_max (&self, area: O::Area) -> O::Unit {
match self.0 { Above | Below | North | South => self.1.w_max(area).max(self.2.w_max(area)), East | West => self.1.w_max(area).plus(self.2.w_max(area)), }
}
fn h (&self, area: O::Area) -> O::Unit {
match self.0 { Above | Below | East | West => self.1.h(area).max(self.2.h(area)), North | South => self.1.h(area).plus(self.2.h(area)), }
}
fn h_min (&self, area: O::Area) -> O::Unit {
match self.0 { Above | Below | East | West => self.1.h_min(area).max(self.2.h_min(area)), North | South => self.1.h_min(area).plus(self.2.h_min(area)), }
}
fn h_max (&self, area: O::Area) -> O::Unit {
match self.0 { Above | Below | North | South => self.1.h_max(area).max(self.2.h_max(area)), East | West => self.1.h_max(area).plus(self.2.h_max(area)), }
}
fn layout (&self, area: O::Area) -> O::Area {
bsp_areas(area, self.0, &self.1, &self.2)[2]
}
} }
fn bsp_areas <O: Out, A: Layout<O>, B: Layout<O>> (area: O::Area, direction: Direction, a: &A, b: &B,) -> [O::Area;3] { fn bsp_areas <O: Out, A: Layout<O>, B: Layout<O>> (area: O::Area, direction: Direction, a: &A, b: &B,) -> [O::Area;3] {

View file

@ -1,138 +0,0 @@
/// Clear a pre-allocated buffer, then write into it.
#[macro_export] macro_rules! rewrite {
($buf:ident, $($rest:tt)*) => { |$buf,_,_|{ $buf.clear(); write!($buf, $($rest)*) } }
}
/// FIXME: This macro should be some variant of `eval`, too.
/// But taking into account the different signatures (resolving them into 1?)
#[cfg(feature = "dsl")] #[macro_export] macro_rules! draw {
($State:ident: $Output:ident: $layers:expr) => {
impl Draw<$Output> for $State {
fn draw (&self, to: &mut $Output) {
for layer in $layers { layer(self, to) }
}
}
}
}
/// FIXME: This is generic: should be called `eval` and be part of [dizzle].
#[cfg(feature = "dsl")] #[macro_export] macro_rules! view {
($State:ident: $Output:ident: $namespaces:expr) => {
impl View<$Output, ()> for $State {
fn view_expr <'a> (&'a self, to: &mut $Output, expr: &'a impl Expression) -> Usually<()> {
for namespace in $namespaces { if namespace(self, to, expr)? { return Ok(()) } }
Err(format!("{}::<{}, ()>::view_expr: unexpected: {expr:?}",
stringify! { $State },
stringify! { $Output }).into())
}
}
}
}
/// Stack things on top of each other,
#[macro_export] macro_rules! lay (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::b(bsp, $expr);)*; bsp }});
/// Stack southward.
#[macro_export] macro_rules! col (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::s(bsp, $expr);)*; bsp }});
/// Stack northward.
#[macro_export] macro_rules! col_up (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::n(bsp, $expr);)*; bsp }});
/// Stack eastward.
#[macro_export] macro_rules! row (($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::e(bsp, $expr);)*; bsp }});
/// Define layout operation.
macro_rules! layout_op_xy (
// Variant for layout ops that take no coordinates
(0: $T: ident) => {
impl<A> $T<A> {
#[inline] pub const fn inner (&self) -> &A {
match self { Self::X(c) | Self::Y(c) | Self::XY(c) => c }
}
}
impl<O: Out, T: Content<O>> Draw<O> for $T<T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
}
};
// Variant for layout ops that take one coordinate
(1: $T: ident) => {
impl<U, A> $T<U, A> {
#[inline] pub const fn inner (&self) -> &A {
match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c, }
}
}
impl<O: Out, T: Content<O>> Draw<O> for $T<O::Unit, T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
}
impl<U: Coord, A> $T<U, A> {
#[inline] pub fn dx (&self) -> U {
match self { Self::X(x, _) | Self::XY(x, ..) => *x, _ => 0.into() }
}
#[inline] pub fn dy (&self) -> U {
match self { Self::Y(y, _) | Self::XY(y, ..) => *y, _ => 0.into() }
}
}
};
(1 opt: $T: ident) => {
impl<U, A> $T<U, A> {
#[inline] pub const fn inner (&self) -> &A {
match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c, }
}
}
impl<O: Out, T: Content<O>> Draw<O> for $T<O::Unit, T> {
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
}
impl<U: Coord, A> $T<U, A> {
#[inline] pub const fn dx (&self) -> Option<U> {
match self { Self::X(x, _) | Self::XY(x, ..) => Some(*x), _ => None }
}
#[inline] pub const fn dy (&self) -> Option<U> {
match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None }
}
}
};
);
// Implement layout op that increments X and/or Y by fixed amount.
macro_rules! push_pull(($T:ident: $method: ident)=>{
layout_op_xy!(1: $T);
impl<O: Out, T: Layout<O>> Layout<O> for $T<O::Unit, T> {
fn x (&self, area: O::Area) -> O::Unit { area.x().$method(self.dx()) }
fn y (&self, area: O::Area) -> O::Unit { area.y().$method(self.dy()) }
}
});
macro_rules! impl_map_direction (($name:ident, $axis:ident, $align:ident)=>{
impl<'a, O, A, B, I, F> Map<
O, A, Push<O::Unit, Align<Fixed<O::Unit, Fill<B>>>>, I, F, fn(A, usize)->B
> where
O: Out,
B: Draw<O>,
I: Iterator<Item = A> + Send + Sync + 'a,
F: Fn() -> I + Send + Sync + 'a
{
pub const fn $name (
size: O::Unit,
get_iter: F,
get_item: impl Fn(A, usize)->B + Send + Sync
) -> Map<
O, A,
Push<O::Unit, Align<Fixed<O::Unit, B>>>,
I, F,
impl Fn(A, usize)->Push<O::Unit, Align<Fixed<O::Unit, B>>> + Send + Sync
> {
Map {
__: PhantomData,
get_iter,
get_item: move |item: A, index: usize|{
// FIXME: multiply
let mut push: O::Unit = O::Unit::from(0u16);
for _ in 0..index {
push = push + size;
}
Push::$axis(push, Align::$align(Fixed::$axis(size, get_item(item, index))))
}
}
}
}
});

View file

@ -1,23 +1,27 @@
use crate::*; use crate::*;
/// A point (X, Y). /// A point (X, Y).
pub struct XY<N: Coord>(N, N); pub struct XY<C: Coord>(pub C, pub C);
/// A size (Width, Height). /// A size (Width, Height).
pub struct WH<N: Coord>(N, N); pub struct WH<C: Coord>(pub C, pub C);
/// Point with size. /// Point with size.
/// ///
/// TODO: anchor field (determines at which corner/side is X0 Y0) /// TODO: anchor field (determines at which corner/side is X0 Y0)
pub struct XYWH<N: Coord>(N, N, N, N); pub struct XYWH<C: Coord>(pub C, pub C, pub C, pub C);
/// A cardinal direction. /// A cardinal direction.
#[derive(Copy, Clone, PartialEq, Debug)] #[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, PartialEq, Debug)] #[cfg_attr(test, derive(Arbitrary))]
pub enum Direction { North, South, East, West, Above, Below } pub enum Direction {
North, South, East, West, Above, Below
}
/// 9th of area to place. /// 9th of area to place.
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } pub enum Alignment {
#[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W
}
/// A widget that tracks its rendered width and height /// A widget that tracks its rendered width and height
#[derive(Default)] pub struct Measure<O: Out> { #[derive(Default)] pub struct Measure<O: Out> {

View file

@ -30,9 +30,9 @@ pub trait Out: Send + Sync + Sized {
/// Unit of length /// Unit of length
type Unit: Coord; type Unit: Coord;
/// Rectangle without offset /// Rectangle without offset
type Size: Size<Self::Unit>; type Size: HasWH<Self::Unit>;
/// Rectangle with offset /// Rectangle with offset
type Area: Area<Self::Unit>; type Area: HasXYWH<Self::Unit>;
/// Current output area /// Current output area
fn area (&self) -> Self::Area; fn area (&self) -> Self::Area;
/// Mutable pointer to area. /// Mutable pointer to area.