mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-02-21 10:39:03 +01:00
wip: refactor(output): 91 more errors...
This commit is contained in:
parent
eaa05b7f09
commit
f033f9ff54
5 changed files with 247 additions and 230 deletions
|
|
@ -16,14 +16,150 @@ pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}
|
|||
pub(crate) use std::marker::PhantomData;
|
||||
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_structs; pub use self::out_structs::*;
|
||||
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(feature = "dsl")]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use crate::*;
|
||||
use Direction::*;
|
||||
use Alignment::*;
|
||||
|
||||
impl Coord for u16 {
|
||||
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 }
|
||||
}
|
||||
|
||||
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> {
|
||||
fn w (&self) -> N { self.0 }
|
||||
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> {
|
||||
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)] }
|
||||
|
|
@ -24,48 +50,49 @@ impl<N: Coord> WH<N> {
|
|||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Coord> XYWH<N> {
|
||||
fn from_position (pos: impl Size<N>) -> Self {
|
||||
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]
|
||||
}
|
||||
/// Iterate over every covered X coordinate.
|
||||
fn iter_x (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
|
||||
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 {
|
||||
self.y()..(self.y()+self.h())
|
||||
}
|
||||
fn clipped (&self, wh: impl Size<N>) -> XYWH<N> {
|
||||
[self.x(), self.y(), wh.w(), wh.h()]
|
||||
fn from_position (pos: impl HasWH<N>) -> Self {
|
||||
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> {
|
||||
[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> {
|
||||
[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]
|
||||
}
|
||||
}
|
||||
|
||||
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<'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 {
|
||||
pub fn split_fixed <N: Coord> (self, area: impl Area<N>, a: N) -> ([N;4],[N;4]) {
|
||||
let [x, y, w, h] = area.xywh();
|
||||
pub fn split_fixed <N: Coord> (self, area: impl HasXYWH<N>, a: N) -> ([N;4],[N;4]) {
|
||||
let XYWH(x, y, w, h) = area.xywh();
|
||||
match self {
|
||||
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)]),
|
||||
|
|
@ -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 {
|
||||
fn size (&self) -> &Measure<E> {
|
||||
self.get()
|
||||
|
|
@ -513,11 +505,20 @@ impl<O: Out, T: Layout<O>> Layout<O> for Align<T> {
|
|||
}
|
||||
|
||||
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> {
|
||||
#[inline] pub fn dx (&self) -> U { match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, } }
|
||||
#[inline] pub fn dy (&self) -> U { match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, } }
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
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> {
|
||||
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> {
|
||||
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_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)), } }
|
||||
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 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_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)), }
|
||||
}
|
||||
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] {
|
||||
|
|
|
|||
|
|
@ -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))))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,23 +1,27 @@
|
|||
use crate::*;
|
||||
|
||||
/// A point (X, Y).
|
||||
pub struct XY<N: Coord>(N, N);
|
||||
pub struct XY<C: Coord>(pub C, pub C);
|
||||
|
||||
/// A size (Width, Height).
|
||||
pub struct WH<N: Coord>(N, N);
|
||||
pub struct WH<C: Coord>(pub C, pub C);
|
||||
|
||||
/// Point with size.
|
||||
///
|
||||
/// 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.
|
||||
#[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.
|
||||
#[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
|
||||
#[derive(Default)] pub struct Measure<O: Out> {
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ pub trait Out: Send + Sync + Sized {
|
|||
/// Unit of length
|
||||
type Unit: Coord;
|
||||
/// Rectangle without offset
|
||||
type Size: Size<Self::Unit>;
|
||||
type Size: HasWH<Self::Unit>;
|
||||
/// Rectangle with offset
|
||||
type Area: Area<Self::Unit>;
|
||||
type Area: HasXYWH<Self::Unit>;
|
||||
/// Current output area
|
||||
fn area (&self) -> Self::Area;
|
||||
/// Mutable pointer to area.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue