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 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")]
|
||||||
|
|
|
||||||
|
|
@ -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] {
|
||||||
|
|
|
||||||
|
|
@ -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::*;
|
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> {
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue