mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 03:36:42 +01:00
uuugh
This commit is contained in:
parent
ca862b9802
commit
90fc869e14
42 changed files with 645 additions and 1158 deletions
|
|
@ -1,40 +1,111 @@
|
|||
use crate::*;
|
||||
|
||||
/// Composable renderable with static dispatch.
|
||||
pub trait Content<E: Out>: Sized {
|
||||
/// Return opaque [Draw]able.
|
||||
fn content (&self) -> impl Draw<E> + Layout<E> + '_ { () }
|
||||
}
|
||||
|
||||
/// The platonic ideal unit of [Content]:
|
||||
/// total emptiness at dead center (e=1vg^sqrt(-1))
|
||||
impl<E: Out> Content<E> for () {}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Content<E> for fn()->T {
|
||||
fn content (&self) -> impl Draw<E> + Layout<E> + '_ {
|
||||
self()
|
||||
pub trait HasContent<O: Out> { fn content (&self) -> impl Content<O>; }
|
||||
pub trait Content<O: Out>: Draw<O> + Layout<O> {}
|
||||
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 { fn as_ref (&self) -> &(dyn Draw<O> + 'a) { self } }
|
||||
impl<'a, O: Out> AsRef<dyn Layout<O> + 'a> for dyn Content<O> + 'a { fn as_ref (&self) -> &(dyn Layout<O> + 'a) { self } }
|
||||
/// Drawable with dynamic dispatch.
|
||||
pub trait Draw<O: Out> { fn draw (&self, to: &mut O); }
|
||||
impl<O: Out> Draw<O> for () { fn draw (&self, to: &mut O) {} }
|
||||
impl<O: Out> Draw<O> for fn(&mut O) { fn draw (&self, to: &mut O) { (*self)(to) } }
|
||||
impl<O: Out> Draw<O> for Box<dyn Draw<O>> { fn draw (&self, to: &mut O) { (**self).draw(to) } }
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for &D { fn draw (&self, to: &mut O) { (*self).draw(to) } }
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for &mut D { fn draw (&self, to: &mut O) { (**self).draw(to) } }
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for Option<D> { fn draw (&self, to: &mut O) { if let Some(draw) = self { draw.draw(to) } } }
|
||||
/// Drawable area of display.
|
||||
pub trait Layout<O: Out> {
|
||||
fn x (&self, to: O::Area) -> O::Unit { to.x() }
|
||||
fn y (&self, to: O::Area) -> O::Unit { to.y() }
|
||||
fn min_w (&self, to: O::Area) -> O::Unit { 0.into() }
|
||||
fn max_w (&self, to: O::Area) -> O::Unit { to.w() }
|
||||
fn w (&self, to: O::Area) -> O::Unit {
|
||||
to.w().max(self.min_w(to)).min(self.max_w(to))
|
||||
}
|
||||
fn min_h (&self, to: O::Area) -> O::Unit { 0.into() }
|
||||
fn max_h (&self, to: O::Area) -> O::Unit { to.h() }
|
||||
fn h (&self, to: O::Area) -> O::Unit {
|
||||
to.h().max(self.min_h(to)).min(self.max_h(to))
|
||||
}
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
[self.x(to), self.y(to), self.w(to), self.h(to)].into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement composable content for a struct.
|
||||
#[macro_export] macro_rules! content {
|
||||
|
||||
// Implement for all [Out]s.
|
||||
(|$self:ident:$Struct:ty| $content:expr) => {
|
||||
impl<E: Out> Content<E> for $Struct {
|
||||
fn content (&$self) -> impl Draw<E> + Layout<E> + '_ { Some($content) }
|
||||
}
|
||||
};
|
||||
|
||||
// Implement for specific [Out].
|
||||
($Out:ty:|
|
||||
$self:ident:
|
||||
$Struct:ident$(<$($($L:lifetime)? $($T:ident)? $(:$Trait:path)?),+>)?
|
||||
|$content:expr) => {
|
||||
impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Content<$Out>
|
||||
for $Struct $(<$($($L)? $($T)?),+>)? {
|
||||
fn content (&$self) -> impl Draw<$Out> + Layout<$Out> + '_ { $content }
|
||||
}
|
||||
};
|
||||
|
||||
impl<O: Out> Layout<O> for () {
|
||||
fn x (&self, a: O::Area) -> O::Unit { a.x() }
|
||||
fn y (&self, a: O::Area) -> O::Unit { a.y() }
|
||||
fn w (&self, _: O::Area) -> O::Unit { 0.into() }
|
||||
fn min_w (&self, _: O::Area) -> O::Unit { 0.into() }
|
||||
fn max_w (&self, _: O::Area) -> O::Unit { 0.into() }
|
||||
fn h (&self, _: O::Area) -> O::Unit { 0.into() }
|
||||
fn min_h (&self, _: O::Area) -> O::Unit { 0.into() }
|
||||
fn max_h (&self, _: O::Area) -> O::Unit { 0.into() }
|
||||
fn layout (&self, a: O::Area) -> O::Area { [a.x(), a.y(), 0.into(), 0.into()].into() }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for &L {
|
||||
fn x (&self, a: O::Area) -> O::Unit { (*self).x(a) }
|
||||
fn y (&self, a: O::Area) -> O::Unit { (*self).y(a) }
|
||||
fn w (&self, a: O::Area) -> O::Unit { (*self).w(a) }
|
||||
fn min_w (&self, a: O::Area) -> O::Unit { (*self).min_w(a) }
|
||||
fn max_w (&self, a: O::Area) -> O::Unit { (*self).max_w(a) }
|
||||
fn h (&self, a: O::Area) -> O::Unit { (*self).h(a) }
|
||||
fn min_h (&self, a: O::Area) -> O::Unit { (*self).min_h(a) }
|
||||
fn max_h (&self, a: O::Area) -> O::Unit { (*self).max_h(a) }
|
||||
fn layout (&self, a: O::Area) -> O::Area { (*self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for &mut L {
|
||||
fn x (&self, a: O::Area) -> O::Unit { (**self).x(a) }
|
||||
fn y (&self, a: O::Area) -> O::Unit { (**self).y(a) }
|
||||
fn w (&self, a: O::Area) -> O::Unit { (**self).w(a) }
|
||||
fn min_w (&self, a: O::Area) -> O::Unit { (**self).min_w(a) }
|
||||
fn max_w (&self, a: O::Area) -> O::Unit { (**self).max_w(a) }
|
||||
fn h (&self, a: O::Area) -> O::Unit { (**self).h(a) }
|
||||
fn min_h (&self, a: O::Area) -> O::Unit { (**self).min_h(a) }
|
||||
fn max_h (&self, a: O::Area) -> O::Unit { (**self).max_h(a) }
|
||||
fn layout (&self, a: O::Area) -> O::Area { (**self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out> Layout<O> for Box<dyn Layout<O>> {
|
||||
fn x (&self, a: O::Area) -> O::Unit { (**self).x(a) }
|
||||
fn y (&self, a: O::Area) -> O::Unit { (**self).y(a) }
|
||||
fn w (&self, a: O::Area) -> O::Unit { (**self).w(a) }
|
||||
fn min_w (&self, a: O::Area) -> O::Unit { (**self).min_w(a) }
|
||||
fn max_w (&self, a: O::Area) -> O::Unit { (**self).max_w(a) }
|
||||
fn h (&self, a: O::Area) -> O::Unit { (**self).h(a) }
|
||||
fn min_h (&self, a: O::Area) -> O::Unit { (**self).min_h(a) }
|
||||
fn max_h (&self, a: O::Area) -> O::Unit { (**self).max_h(a) }
|
||||
fn layout (&self, a: O::Area) -> O::Area { (**self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Option<L> {
|
||||
fn x (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.x(to)).unwrap_or(to.x())
|
||||
}
|
||||
fn y (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.y(to)).unwrap_or(to.y())
|
||||
}
|
||||
fn min_w (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.min_w(to)).unwrap_or(0.into())
|
||||
}
|
||||
fn max_w (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.max_w(to)).unwrap_or(0.into())
|
||||
}
|
||||
fn w (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.w(to)).unwrap_or(0.into())
|
||||
}
|
||||
fn min_h (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.min_h(to)).unwrap_or(0.into())
|
||||
}
|
||||
fn max_h (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.max_h(to)).unwrap_or(0.into())
|
||||
}
|
||||
fn h (&self, to: O::Area) -> O::Unit {
|
||||
self.as_ref().map(|c|c.h(to)).unwrap_or(0.into())
|
||||
}
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
self.as_ref().map(|c|c.layout([self.x(to), self.y(to), self.w(to), self.h(to)].into()))
|
||||
.unwrap_or([to.x(), to.y(), 0.into(), 0.into()].into())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,94 +1,27 @@
|
|||
use crate::*;
|
||||
|
||||
/// Drawable with dynamic dispatch.
|
||||
pub trait Draw<O: Out> {
|
||||
/// Write data to display.
|
||||
fn draw (&self, to: &mut O);
|
||||
pub struct Bound<O: Out, D>(pub O::Area, pub D);
|
||||
|
||||
impl<O: Out, D: Content<O>> HasContent<O> for Bound<O, D> {
|
||||
fn content (&self) -> &impl Content<O> { &self.1 }
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for fn(&mut O) {
|
||||
impl<O: Out, T> Layout<O> for Bound<O, T> {
|
||||
fn x (&self, _: O::Area) -> O::Unit { self.0.x() }
|
||||
fn y (&self, _: O::Area) -> O::Unit { self.0.y() }
|
||||
fn w (&self, _: O::Area) -> O::Unit { self.0.w() }
|
||||
fn min_w (&self, _: O::Area) -> O::Unit { self.0.w() }
|
||||
fn max_w (&self, _: O::Area) -> O::Unit { self.0.w() }
|
||||
fn h (&self, _: O::Area) -> O::Unit { self.0.h() }
|
||||
fn min_h (&self, _: O::Area) -> O::Unit { self.0.w() }
|
||||
fn max_h (&self, _: O::Area) -> O::Unit { self.0.w() }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Bound<O, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
self(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for () { fn draw (&self, _: &mut O) {} }
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for &T {
|
||||
fn draw (&self, to: &mut O) { (*self).draw(to) }
|
||||
}
|
||||
|
||||
impl<'x, O: Out> Draw<O> for &(dyn Draw<O> + 'x) {
|
||||
fn draw (&self, to: &mut O) {
|
||||
(*self).draw(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x, O: Out> Draw<O> for &mut (dyn Draw<O> + 'x) {
|
||||
fn draw (&self, to: &mut O) {
|
||||
(**self).draw(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for RwLock<T> {
|
||||
fn draw (&self, to: &mut O) { self.read().unwrap().draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for [T] {
|
||||
fn draw (&self, to: &mut O) {
|
||||
for draw in self.iter() {
|
||||
draw.draw(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//impl<O: Out, T: Draw<O>> Draw<O> for &mut T {
|
||||
//fn draw (&self, to: &mut O) {
|
||||
//(**self).draw(to)
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<O: Out, T: Iterator<Item = U>, U: Draw<O>> Draw<O> for &mut T {
|
||||
//fn draw (&self, to: &mut O) {
|
||||
//for draw in *self {
|
||||
//draw.draw(to)
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
/// Implement custom drawing for a struct.
|
||||
#[macro_export] macro_rules! draw {
|
||||
|
||||
// Implement for all [Out] backends.
|
||||
(|$self:ident:$Struct:ident $(<
|
||||
$($L:lifetime),* $($T:ident $(:$Trait:path)?),*
|
||||
>)?, $to:ident | $draw:expr) => {
|
||||
impl <$($($L),*)? O: Out, $($($T$(:$Trait)?),*)?> Draw<O>
|
||||
for $Struct $(<$($L),* $($T),*>)? {
|
||||
fn draw (&$self, $to: &mut O) { $draw }
|
||||
}
|
||||
};
|
||||
|
||||
// Implement for a specific [Out] backend.
|
||||
($O:ty:|
|
||||
$self:ident:
|
||||
$Struct:ident $(<$($($L:lifetime)? $($T:ident)? $(:$Trait:path)?),+>)?, $to:ident
|
||||
|$draw:expr) => {
|
||||
impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Draw<$O>
|
||||
for $Struct $(<$($($L)? $($T)?),+>)? {
|
||||
fn draw (&$self, $to: &mut $O) { $draw }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
draw!(|self: Arc<T: Draw<O>>, to|(**self).draw(to));
|
||||
draw!(|self: Box<T: Draw<O>>, to|(**self).draw(to));
|
||||
//draw!(|self: Option<T: Draw<O>>, to|if let Some(draw) = self { draw.draw(to) });
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Option<T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
if let Some(draw) = self {
|
||||
draw.draw(to)
|
||||
}
|
||||
let area = to.area();
|
||||
*to.area_mut() = self.0;
|
||||
self.1.draw(to);
|
||||
*to.area_mut() = area;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,98 +1,10 @@
|
|||
use crate::*;
|
||||
|
||||
pub trait Layout<O: Out> {
|
||||
fn x (&self, area: O::Area) -> O::Unit {
|
||||
area.x()
|
||||
}
|
||||
fn y (&self, area: O::Area) -> O::Unit {
|
||||
area.y()
|
||||
}
|
||||
|
||||
fn min_w (&self, _area: O::Area) -> O::Unit {
|
||||
0.into()
|
||||
}
|
||||
fn max_w (&self, area: O::Area) -> O::Unit {
|
||||
area.w()
|
||||
}
|
||||
|
||||
fn min_h (&self, _area: O::Area) -> O::Unit {
|
||||
0.into()
|
||||
}
|
||||
fn max_h (&self, area: O::Area) -> O::Unit {
|
||||
area.h()
|
||||
}
|
||||
|
||||
fn layout (&self, area: O::Area) -> O::Area {
|
||||
O::Area::from([
|
||||
self.x(area),
|
||||
self.y(area),
|
||||
area.w().max(self.min_w(area)).min(self.max_w(area)),
|
||||
area.h().max(self.min_h(area)).min(self.max_h(area)),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! layout {
|
||||
// Implement for all [Out] backends.
|
||||
(|$self:ident:$Struct:ident $(<
|
||||
$($L:lifetime),* $($T:ident $(:$Trait:path)?),*
|
||||
>)?, $to:ident|$($method:ident = |$area:ident|$body:expr;)*) => {
|
||||
impl <$($($L),*)? O: Out, $($($T$(:$Trait)?),*)?> Layout<O>
|
||||
for $Struct $(<$($L),* $($T),*>)? {
|
||||
$(fn $method (&$self, $area: O::Area) -> O::Area {
|
||||
$body
|
||||
})*
|
||||
}
|
||||
};
|
||||
// Implement for a specific [Out] backend.
|
||||
($O:ty:|
|
||||
$self:ident:
|
||||
$Struct:ident $(<$($($L:lifetime)? $($T:ident)? $(:$Trait:path)?),+>)?,
|
||||
$to:ident
|
||||
|$($method:ident = |$area:ident|$body:expr;)*) => {
|
||||
impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Layout<$O>
|
||||
for $Struct $(<$($($L)? $($T)?),+>)? {
|
||||
$(fn $method (&$self, $area: <$O as Out>::Area) -> <$O as Out>::Area {
|
||||
$body
|
||||
})*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<O: Out> Layout<O> for () {}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for &L { /*FIXME*/ }
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for RwLock<L> { /*FIXME*/ }
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Option<L> { /*FIXME*/ }
|
||||
|
||||
//impl<O: Out> Layout<O> for fn(&mut O) {}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Arc<L> {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
(**self).layout(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x, O: Out> Layout<O> for &(dyn Draw<O> + 'x) {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
Fill::xy(self).layout(to)
|
||||
}
|
||||
}
|
||||
|
||||
mod layout_align; pub use self::layout_align::*;
|
||||
mod layout_bsp; pub use self::layout_bsp::*;
|
||||
mod layout_cond; pub use self::layout_cond::*;
|
||||
mod layout_expand; pub use self::layout_expand::*;
|
||||
mod layout_fill; pub use self::layout_fill::*;
|
||||
mod layout_fixed; pub use self::layout_fixed::*;
|
||||
mod layout_map; pub use self::layout_map::*;
|
||||
mod layout_margin; pub use self::layout_margin::*;
|
||||
mod layout_max; pub use self::layout_max::*;
|
||||
mod layout_min; pub use self::layout_min::*;
|
||||
mod layout_padding; pub use self::layout_padding::*;
|
||||
mod layout_pull; pub use self::layout_pull::*;
|
||||
mod layout_push; pub use self::layout_push::*;
|
||||
mod layout_shrink; pub use self::layout_shrink::*;
|
||||
mod layout_stack; //pub use self::layout_stack::*;
|
||||
mod layout_align; pub use self::layout_align::*;
|
||||
mod layout_bsp; pub use self::layout_bsp::*;
|
||||
mod layout_cond; pub use self::layout_cond::*;
|
||||
mod layout_map; pub use self::layout_map::*;
|
||||
mod layout_pad; pub use self::layout_pad::*;
|
||||
mod layout_move; pub use self::layout_move::*;
|
||||
mod layout_size; pub use self::layout_size::*;
|
||||
mod layout_stack; //pub use self::layout_stack::*;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//! assert_eq!(Draw::layout(item, area), expected);
|
||||
//! };
|
||||
//!
|
||||
//! let four = ||Fixed::xy(4, 4, "");
|
||||
//! let four = ||Fixed::XY(4, 4, "");
|
||||
//! test(area, &Align::nw(four()), [10, 10, 4, 4]);
|
||||
//! test(area, &Align::n(four()), [18, 10, 4, 4]);
|
||||
//! test(area, &Align::ne(four()), [26, 10, 4, 4]);
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
//! test(area, &Align::sw(four()), [10, 26, 4, 4]);
|
||||
//! test(area, &Align::w(four()), [10, 18, 4, 4]);
|
||||
//!
|
||||
//! let two_by_four = ||Fixed::xy(4, 2, "");
|
||||
//! let two_by_four = ||Fixed::XY(4, 2, "");
|
||||
//! test(area, &Align::nw(two_by_four()), [10, 10, 4, 2]);
|
||||
//! test(area, &Align::n(two_by_four()), [18, 10, 4, 2]);
|
||||
//! test(area, &Align::ne(two_by_four()), [26, 10, 4, 2]);
|
||||
|
|
@ -27,13 +27,12 @@
|
|||
//! test(area, &Align::w(two_by_four()), [10, 19, 4, 2]);
|
||||
//! ```
|
||||
use crate::*;
|
||||
use Alignment::*;
|
||||
|
||||
/// 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 struct Align<T>(Alignment, T);
|
||||
|
||||
impl<T> Align<T> {
|
||||
#[inline] pub const fn c (a: T) -> Self { Self(Alignment::Center, a) }
|
||||
#[inline] pub const fn x (a: T) -> Self { Self(Alignment::X, a) }
|
||||
|
|
@ -47,39 +46,24 @@ impl<T> Align<T> {
|
|||
#[inline] pub const fn ne (a: T) -> Self { Self(Alignment::NE, a) }
|
||||
#[inline] pub const fn se (a: T) -> Self { Self(Alignment::SE, a) }
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Align<T> {
|
||||
fn layout (&self, on: E::Area) -> E::Area {
|
||||
self.0.align(on, &self.1)
|
||||
}
|
||||
}
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Align<T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Alignment {
|
||||
fn align <E: Out> (&self, on: E::Area, content: &impl Layout<E>) -> E::Area {
|
||||
use Alignment::*;
|
||||
let it = content.layout(on).xywh();
|
||||
let cx = on.x()+(on.w().minus(it.w())/2.into());
|
||||
let cy = on.y()+(on.h().minus(it.h())/2.into());
|
||||
let fx = (on.x()+on.w()).minus(it.w());
|
||||
let fy = (on.y()+on.h()).minus(it.h());
|
||||
let [x, y] = match self {
|
||||
Center => [cx, cy],
|
||||
X => [cx, it.y()],
|
||||
Y => [it.x(), cy],
|
||||
NW => [on.x(), on.y()],
|
||||
N => [cx, on.y()],
|
||||
NE => [fx, on.y()],
|
||||
W => [on.x(), cy],
|
||||
E => [fx, cy],
|
||||
SW => [on.x(), fy],
|
||||
S => [cx, fy],
|
||||
SE => [fx, fy],
|
||||
};
|
||||
[x, y, it.w(), it.h()].into()
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Align<T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), &self.1).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Align<T> {
|
||||
fn x (&self, to: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
NW | W | SW => to.x(),
|
||||
N | Center | S => to.x().plus(to.w() / 2.into()).minus(self.1.w(to) / 2.into()),
|
||||
NE | E | SE => to.x().plus(to.w()).minus(self.1.w(to)),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
fn y (&self, to: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
NW | N | NE => to.y(),
|
||||
W | Center | E => to.y().plus(to.h() / 2.into()).minus(self.1.h(to) / 2.into()),
|
||||
SW | S | SE => to.y().plus(to.h()).minus(self.1.h(to)),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::*;
|
||||
use Direction::*;
|
||||
|
||||
/// A split or layer.
|
||||
/// A binary split or layer.
|
||||
pub struct Bsp<Head, Tail>(
|
||||
pub(crate) Direction,
|
||||
/// First element.
|
||||
|
|
@ -19,31 +18,79 @@ impl<Head, Tail> Bsp<Head, Tail> {
|
|||
#[inline] pub const fn b (a: Head, b: Tail) -> Self { Self(Below, a, b) }
|
||||
}
|
||||
|
||||
impl<
|
||||
O: Out,
|
||||
Head: Draw<O> + Layout<O>,
|
||||
Tail: Draw<O> + Layout<O>
|
||||
> Draw<O> for Bsp<Head, Tail> {
|
||||
impl<O: Out, Head: Content<O>, Tail: Content<O>> Draw<O> for Bsp<Head, Tail> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let [a, b, _] = bsp_areas(to.area(), self.0, &self.1, &self.2);
|
||||
if self.0 == Below {
|
||||
to.place_at(a, &self.1);
|
||||
to.place_at(b, &self.2);
|
||||
} else {
|
||||
to.place_at(b, &self.2);
|
||||
to.place_at(a, &self.1);
|
||||
match self.0 {
|
||||
South => {
|
||||
panic!("{}", self.1.h(to.area()));
|
||||
let area_1 = self.1.layout(to.area());
|
||||
let area_2 = self.2.layout([
|
||||
to.area().x(),
|
||||
to.area().y().plus(area_1.h()),
|
||||
to.area().w(),
|
||||
to.area().h().minus(area_1.h())
|
||||
].into());
|
||||
panic!("{area_1:?} {area_2:?}");
|
||||
to.place_at(area_1, &self.1);
|
||||
to.place_at(area_2, &self.2);
|
||||
},
|
||||
_ => todo!("{:?}", self.0)
|
||||
}
|
||||
//let [a, b, _] = bsp_areas(to.area(), self.0, &self.1, &self.2);
|
||||
//panic!("{a:?} {b:?}");
|
||||
//if self.0 == Below {
|
||||
//to.place_at(a, &self.1);
|
||||
//to.place_at(b, &self.2);
|
||||
//} else {
|
||||
//to.place_at(b, &self.2);
|
||||
//to.place_at(a, &self.1);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
North | South | Above | Below => self.1.w(area).max(self.2.w(area)),
|
||||
East | West => self.1.min_w(area).plus(self.2.w(area)),
|
||||
}
|
||||
}
|
||||
fn min_w (&self, area: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
North | South | Above | Below => self.1.min_w(area).max(self.2.min_w(area)),
|
||||
East | West => self.1.min_w(area).plus(self.2.min_w(area)),
|
||||
}
|
||||
}
|
||||
fn max_w (&self, area: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
North | South | Above | Below => self.1.max_w(area).max(self.2.max_w(area)),
|
||||
East | West => self.1.max_w(area).plus(self.2.max_w(area)),
|
||||
}
|
||||
}
|
||||
fn h (&self, area: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
East | West | Above | Below => self.1.h(area).max(self.2.h(area)),
|
||||
North | South => self.1.h(area).plus(self.2.h(area)),
|
||||
}
|
||||
}
|
||||
fn min_h (&self, area: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
East | West | Above | Below => self.1.min_h(area).max(self.2.min_h(area)),
|
||||
North | South => self.1.min_h(area).plus(self.2.min_h(area)),
|
||||
}
|
||||
}
|
||||
fn max_h (&self, area: O::Area) -> O::Unit {
|
||||
match self.0 {
|
||||
North | South | Above | Below => self.1.max_h(area).max(self.2.max_h(area)),
|
||||
East | West => self.1.max_h(area).plus(self.2.max_h(area)),
|
||||
}
|
||||
}
|
||||
fn layout (&self, area: O::Area) -> O::Area {
|
||||
bsp_areas(area, self.0, &self.1, &self.2)[2]
|
||||
}
|
||||
}
|
||||
|
||||
fn bsp_areas <O: Out> (
|
||||
area: O::Area, direction: Direction, a: &impl Layout<O>, b: &impl Layout<O>,
|
||||
fn bsp_areas <O: Out, A: Layout<O>, B: Layout<O>> (
|
||||
area: O::Area, direction: Direction, a: &A, b: &B,
|
||||
) -> [O::Area;3] {
|
||||
let [x, y, w, h] = area.xywh();
|
||||
let [aw, ah] = a.layout(area).wh();
|
||||
|
|
|
|||
|
|
@ -2,54 +2,45 @@ use crate::*;
|
|||
|
||||
/// Show an item only when a condition is true.
|
||||
pub struct When<O, T>(bool, T, PhantomData<O>);
|
||||
impl<O, T> When<O, T> {
|
||||
impl<O: Out, T: Content<O>> When<O, T> {
|
||||
/// Create a binary condition.
|
||||
pub const fn new (c: bool, a: T) -> Self { Self(c, a, PhantomData) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for When<O, T> {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
let Self(cond, item, ..) = self;
|
||||
let mut area = O::Area::zero();
|
||||
if *cond {
|
||||
let item_area = item.layout(to);
|
||||
area[0] = item_area.x();
|
||||
area[1] = item_area.y();
|
||||
area[2] = item_area.w();
|
||||
area[3] = item_area.h();
|
||||
}
|
||||
area.into()
|
||||
if *cond { item.layout(to) } else { O::Area::zero().into() }
|
||||
}
|
||||
}
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for When<O, T> {
|
||||
impl<O: Out, T: Content<O>> Draw<O> for When<O, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let Self(cond, item, ..) = self;
|
||||
if *cond { item.draw(to) }
|
||||
if *cond { Bound(self.layout(to.area()), item).draw(to) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Show one item if a condition is true and another if the condition is false
|
||||
pub struct Either<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>>(pub bool, pub A, pub B, pub PhantomData<E>);
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Either<E, A, B> {
|
||||
pub struct Either<E: Out, A, B>(pub bool, pub A, pub B, pub PhantomData<E>);
|
||||
impl<E: Out, A: Content<E>, B: Content<E>> Either<E, A, B> {
|
||||
/// Create a ternary view condition.
|
||||
pub const fn new (c: bool, a: A, b: B) -> Self {
|
||||
Self(c, a, b, PhantomData)
|
||||
}
|
||||
}
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Layout<E> for Either<E, A, B> {
|
||||
impl<E: Out, A: Layout<E>, B: Layout<E>> Layout<E> for Either<E, A, B> {
|
||||
fn layout (&self, to: E::Area) -> E::Area {
|
||||
let Self(cond, a, b, ..) = self;
|
||||
if *cond { a.layout(to) } else { b.layout(to) }
|
||||
}
|
||||
}
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Draw<E> for Either<E, A, B> {
|
||||
impl<E: Out, A: Content<E>, B: Content<E>> Draw<E> for Either<E, A, B> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
let Self(cond, a, b, ..) = self;
|
||||
if *cond { a.draw(to) } else { b.draw(to) }
|
||||
let area = self.layout(to.area());
|
||||
if *cond { Bound(area, a).draw(to) } else { Bound(area, b).draw(to) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
@ -116,7 +107,7 @@ impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Draw<E> for Either<
|
|||
//return Ok(Some(match words.next() {
|
||||
//Some(Token{value: Key($x),..}) => Self::x(content),
|
||||
//Some(Token{value: Key($y),..}) => Self::y(content),
|
||||
//Some(Token{value: Key($xy),..}) => Self::xy(content),
|
||||
//Some(Token{value: Key($xy),..}) => Self::XY(content),
|
||||
//_ => unreachable!()
|
||||
//}))
|
||||
//} else {
|
||||
|
|
@ -134,7 +125,7 @@ impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Draw<E> for Either<
|
|||
//state.give_or_fail(words, ||"y: no unit")?,
|
||||
//state.give_or_fail(words, ||"y: no content")?,
|
||||
//),
|
||||
//Some(Token { value: Key($x), .. }) => Self::xy(
|
||||
//Some(Token { value: Key($x), .. }) => Self::XY(
|
||||
//state.give_or_fail(words, ||"xy: no unit x")?,
|
||||
//state.give_or_fail(words, ||"xy: no unit y")?,
|
||||
//state.give_or_fail(words, ||"xy: no content")?
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Expand<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Expand<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self { Self::X(x, item) }
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self { Self::Y(y, item) }
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self { Self::XY(x, y, item) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O> + Layout<O>> Content<O> for Expand<O::Unit, T> {
|
||||
fn content (&self) -> impl Draw<O> + Layout<O> + '_ {
|
||||
use Expand::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O> + Layout<O>> Draw<O> for Expand<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Expand<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Expand::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Expand::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Expand<O::Unit, T> {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
[to.x(), to.y(), to.w().plus(self.dx()), to.h().plus(self.dy())].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Fill<A> {
|
||||
/// Use maximum width of area.
|
||||
X(A),
|
||||
/// Use maximum height of area.
|
||||
Y(A),
|
||||
/// Use maximum width and height of area.
|
||||
XY(A)
|
||||
}
|
||||
|
||||
impl<T> Fill<T> {
|
||||
#[inline] pub const fn x (item: T) -> Self {
|
||||
Self::X(item)
|
||||
}
|
||||
#[inline] pub const fn y (item: T) -> Self {
|
||||
Self::Y(item)
|
||||
}
|
||||
#[inline] pub const fn xy (item: T) -> Self {
|
||||
Self::XY(item)
|
||||
}
|
||||
#[inline] pub const fn has_x (&self) -> bool {
|
||||
matches!(self, Self::X(_) | Self::XY(_))
|
||||
}
|
||||
#[inline] pub const fn has_y (&self) -> bool {
|
||||
matches!(self, Self::Y(_) | Self::XY(_))
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &T {
|
||||
use Fill::*;
|
||||
match self { X(item) | Y(item) | XY(item) => item }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Fill<T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Layout<O> for Fill<T> {
|
||||
fn min_w (&self, area: O::Area) -> O::Unit {
|
||||
if self.has_x() {
|
||||
area.w()
|
||||
} else {
|
||||
0.into()
|
||||
}
|
||||
}
|
||||
fn min_h (&self, area: O::Area) -> O::Unit {
|
||||
if self.has_y() {
|
||||
area.h()
|
||||
} else {
|
||||
0.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Fixed<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Fixed<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Fixed::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Fixed<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Fixed::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Fixed::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Fixed<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let area = Layout::<O>::layout(&self, to.area());
|
||||
to.place_at(area, &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T> Layout<O> for Fixed<O::Unit, T> {
|
||||
fn layout (&self, area: O::Area) -> O::Area {
|
||||
[area.x(), area.y(), match self {
|
||||
Fixed::X(w, _) | Fixed::XY(w, _, _) => *w, _ => area.w()
|
||||
}, match self {
|
||||
Fixed::Y(h, _) | Fixed::XY(_, h, _) => *h, _ => area.h()
|
||||
}].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ macro_rules! impl_map_direction (($name:ident, $axis:ident, $align:ident)=>{
|
|||
O, A, Push<O::Unit, Align<Fixed<O::Unit, Fill<B>>>>, I, F, fn(A, usize)->B
|
||||
> where
|
||||
O: Out,
|
||||
B: Draw<O> + Layout<O>,
|
||||
B: Draw<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a
|
||||
{
|
||||
|
|
@ -61,14 +61,14 @@ macro_rules! impl_map_direction (($name:ident, $axis:ident, $align:ident)=>{
|
|||
}
|
||||
});
|
||||
|
||||
impl_map_direction!(east, x, w);
|
||||
impl_map_direction!(south, y, n);
|
||||
impl_map_direction!(west, x, e);
|
||||
impl_map_direction!(north, y, s);
|
||||
impl_map_direction!(east, X, w);
|
||||
impl_map_direction!(south, Y, n);
|
||||
impl_map_direction!(west, X, e);
|
||||
impl_map_direction!(north, Y, s);
|
||||
|
||||
impl<'a, O, A, B, I, F, G> Layout<O> for Map<O, A, B, I, F, G> where
|
||||
O: Out,
|
||||
B: Draw<O> + Layout<O>,
|
||||
B: Layout<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
G: Fn(A, usize)->B + Send + Sync
|
||||
|
|
@ -94,7 +94,7 @@ impl<'a, O, A, B, I, F, G> Layout<O> for Map<O, A, B, I, F, G> where
|
|||
}
|
||||
impl<'a, O, A, B, I, F, G> Draw<O> for Map<O, A, B, I, F, G> where
|
||||
O: Out,
|
||||
B: Draw<O> + Layout<O>,
|
||||
B: Content<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
G: Fn(A, usize)->B + Send + Sync
|
||||
|
|
@ -115,25 +115,25 @@ impl<'a, O, A, B, I, F, G> Draw<O> for Map<O, A, B, I, F, G> where
|
|||
#[inline] pub fn map_south<O: Out>(
|
||||
item_offset: O::Unit,
|
||||
item_height: O::Unit,
|
||||
item: impl Draw<O> + Layout<O>
|
||||
) -> impl Draw<O> + Layout<O> {
|
||||
Push::y(item_offset, Fixed::y(item_height, Fill::x(item)))
|
||||
item: impl Content<O>
|
||||
) -> impl Content<O> {
|
||||
Push::Y(item_offset, Fixed::Y(item_height, Fill::X(item)))
|
||||
}
|
||||
|
||||
#[inline] pub fn map_south_west<O: Out>(
|
||||
item_offset: O::Unit,
|
||||
item_height: O::Unit,
|
||||
item: impl Draw<O> + Layout<O>
|
||||
) -> impl Draw<O> + Layout<O> {
|
||||
Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item))))
|
||||
item: impl Content<O>
|
||||
) -> impl Content<O> {
|
||||
Push::Y(item_offset, Align::nw(Fixed::Y(item_height, Fill::X(item))))
|
||||
}
|
||||
|
||||
#[inline] pub fn map_east<O: Out>(
|
||||
item_offset: O::Unit,
|
||||
item_width: O::Unit,
|
||||
item: impl Draw<O> + Layout<O>
|
||||
) -> impl Draw<O> + Layout<O> {
|
||||
Push::x(item_offset, Align::w(Fixed::x(item_width, Fill::y(item))))
|
||||
item: impl Content<O>
|
||||
) -> impl Content<O> {
|
||||
Push::X(item_offset, Align::w(Fixed::X(item_width, Fill::Y(item))))
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Margin<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Margin<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Margin::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Margin<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Margin<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Margin::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Margin::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Margin<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let area = self.content().layout(area);
|
||||
let dx = self.dx();
|
||||
let dy = self.dy();
|
||||
[
|
||||
area.x().minus(dx),
|
||||
area.y().minus(dy),
|
||||
area.w().plus(dy.plus(dy)),
|
||||
area.h().plus(dy.plus(dy)),
|
||||
].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Max<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Max<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Max::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Max<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Max<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Max::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Max::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Max<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let [x, y, w, h] = self.content().layout(area).xywh();
|
||||
match self {
|
||||
Self::X(mw, _) => [x, y, w.min(*mw), h],
|
||||
Self::Y(mh, _) => [x, y, w, h.min(*mh)],
|
||||
Self::XY(mw, mh, _) => [x, y, w.min(*mw), h.min(*mh)],
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Min<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Min<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Min::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Min<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Min<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Min::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Min::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Min<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let [x, y, w, h] = self.content().layout(area).xywh();
|
||||
match self {
|
||||
Self::X(mw, _) => [x, y, w.max(*mw), h],
|
||||
Self::Y(mh, _) => [x, y, w, h.max(*mh)],
|
||||
Self::XY(mw, mh, _) => [x, y, w.max(*mw), h.max(*mh)],
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
33
output/src/layout/layout_move.rs
Normal file
33
output/src/layout/layout_move.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use crate::*;
|
||||
/// Increment X and/or Y coordinate.
|
||||
pub enum Push<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Push<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c, } }
|
||||
}
|
||||
impl<U: Coordinate, T> Push<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U { match self { Self::X(x, ..) | Self::XY(x, _, _) => *x, Self::Y(_, _) => 0.into() } }
|
||||
#[inline] pub fn dy (&self) -> U { match self { Self::Y(y, ..) | Self::XY(_, y, _) => *y, Self::X(_, _) => 0.into() } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Push<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Push<O::Unit, T> {
|
||||
fn x (&self, area: O::Area) -> O::Unit { area.x().plus(self.dx()) }
|
||||
fn y (&self, area: O::Area) -> O::Unit { area.y().plus(self.dy()) }
|
||||
}
|
||||
/// Decrement X and/or Y coordinate.
|
||||
pub enum Pull<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Pull<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c, } }
|
||||
}
|
||||
impl<U: Coordinate, T> Pull<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U { match self { Self::X(x, ..) | Self::XY(x, _, _) => *x, Self::Y(_, _) => 0.into() } }
|
||||
#[inline] pub fn dy (&self) -> U { match self { Self::Y(y, ..) | Self::XY(_, y, _) => *y, Self::X(_, _) => 0.into() } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Pull<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Pull<O::Unit, T> {
|
||||
fn x (&self, area: O::Area) -> O::Unit { area.x().minus(self.dx()) }
|
||||
fn y (&self, area: O::Area) -> O::Unit { area.y().minus(self.dy()) }
|
||||
}
|
||||
27
output/src/layout/layout_pad.rs
Normal file
27
output/src/layout/layout_pad.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
use crate::*;
|
||||
use Pad::*;
|
||||
pub enum Pad<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Pad<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { X(_, c) | Y(_, c) | XY(_, _, c) => c, } }
|
||||
}
|
||||
impl<U: Coordinate, 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, } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Pad<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Pad<O::Unit, T> {
|
||||
fn x (&self, area: O::Area) -> O::Unit {
|
||||
area.x().plus(self.dx())
|
||||
}
|
||||
fn y (&self, area: O::Area) -> O::Unit {
|
||||
area.x().plus(self.dx())
|
||||
}
|
||||
fn w (&self, area: O::Area) -> O::Unit {
|
||||
area.w().minus(self.dx() * 2.into())
|
||||
}
|
||||
fn h (&self, area: O::Area) -> O::Unit {
|
||||
area.h().minus(self.dy() * 2.into())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Padding<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Padding<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Padding::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Padding<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Padding<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Padding::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Padding::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Padding<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let area = self.content().layout(area);
|
||||
let dx = self.dx();
|
||||
let dy = self.dy();
|
||||
[
|
||||
area.x().plus(dx),
|
||||
area.y().plus(dy),
|
||||
area.w().minus(dy.plus(dy)),
|
||||
area.h().minus(dy.plus(dy))
|
||||
].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Pull<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Pull<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Pull::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Pull<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Pull<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Pull::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Pull::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Pull<E::Unit, T> {
|
||||
fn layout (&self, to: E::Area) -> E::Area {
|
||||
let area = self.content().layout(to);
|
||||
[
|
||||
area.x().minus(self.dx()),
|
||||
area.y().minus(self.dy()),
|
||||
area.w(),
|
||||
area.h()
|
||||
].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Push<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Push<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Push::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Push<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Push<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Push::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Push::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Push<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let area = self.content().layout(area);
|
||||
[area.x().plus(self.dx()), area.y().plus(self.dy()), area.w(), area.h()].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Shrink<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
|
||||
impl<U, A> Shrink<U, A> {
|
||||
#[inline] pub const fn x (x: U, item: A) -> Self {
|
||||
Self::X(x, item)
|
||||
}
|
||||
#[inline] pub const fn y (y: U, item: A) -> Self {
|
||||
Self::Y(y, item)
|
||||
}
|
||||
#[inline] pub const fn xy (x: U, y: U, item: A) -> Self {
|
||||
Self::XY(x, y, item)
|
||||
}
|
||||
#[inline] pub const fn content (&self) -> &A {
|
||||
use Shrink::*;
|
||||
match self { X(_, c) => c, Y(_, c) => c, XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Shrink<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coordinate, T> Shrink<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Shrink::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Shrink::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Shrink<E::Unit, T> {
|
||||
fn layout (&self, to: E::Area) -> E::Area {
|
||||
let area = self.content().layout(to);
|
||||
[area.x(), area.y(), area.w().minus(self.dx()), area.h().minus(self.dy())].into()
|
||||
}
|
||||
}
|
||||
121
output/src/layout/layout_size.rs
Normal file
121
output/src/layout/layout_size.rs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Fill<A> { X(A), Y(A), XY(A) }
|
||||
impl<A> Fill<A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(c) | Self::Y(c) | Self::XY(c) => c } }
|
||||
#[inline] pub const fn dx (&self) -> bool { match self { Self::X(_) | Self::XY(_) => true, _ => false } }
|
||||
#[inline] pub const fn dy (&self) -> bool { match self { Self::Y(_) | Self::XY(_) => true, _ => false } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Fill<T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Fill<T> {
|
||||
fn x (&self, area: O::Area) -> O::Unit { if self.dx() { area.x() } else { self.inner().x(area) } }
|
||||
fn y (&self, area: O::Area) -> O::Unit { if self.dy() { area.y() } else { self.inner().y(area) } }
|
||||
fn w (&self, area: O::Area) -> O::Unit { if self.dx() { area.w() } else { self.inner().w(area) } }
|
||||
fn min_w (&self, area: O::Area) -> O::Unit { if self.dx() { area.w() } else { self.inner().min_w(area) } }
|
||||
fn max_w (&self, area: O::Area) -> O::Unit { if self.dx() { area.w() } else { self.inner().max_w(area) } }
|
||||
fn h (&self, area: O::Area) -> O::Unit { if self.dy() { area.h() } else { self.inner().h(area) } }
|
||||
fn min_h (&self, area: O::Area) -> O::Unit { if self.dy() { area.h() } else { self.inner().min_h(area) } }
|
||||
fn max_h (&self, area: O::Area) -> O::Unit { if self.dy() { area.h() } else { self.inner().max_h(area) } }
|
||||
}
|
||||
/// Set fixed size for content.
|
||||
pub enum Fixed<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Fixed<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c } }
|
||||
}
|
||||
impl<U: Copy, A> Fixed<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 } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Fixed<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Fixed<O::Unit, T> {
|
||||
fn w (&self, area: O::Area) -> O::Unit { self.dx().unwrap_or(self.inner().w(area)) }
|
||||
fn min_w (&self, area: O::Area) -> O::Unit { self.dx().unwrap_or(self.inner().min_w(area)) }
|
||||
fn max_w (&self, area: O::Area) -> O::Unit { self.dx().unwrap_or(self.inner().max_w(area)) }
|
||||
fn h (&self, area: O::Area) -> O::Unit { self.dy().unwrap_or(self.inner().h(area)) }
|
||||
fn min_h (&self, area: O::Area) -> O::Unit { self.dy().unwrap_or(self.inner().min_h(area)) }
|
||||
fn max_h (&self, area: O::Area) -> O::Unit { self.dy().unwrap_or(self.inner().max_h(area)) }
|
||||
}
|
||||
|
||||
pub enum Max<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Max<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c } }
|
||||
}
|
||||
impl<U: Copy, A> Max<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 } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Max<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Max<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let [x, y, w, h] = self.inner().layout(area).xywh();
|
||||
match self {
|
||||
Self::X(mw, _) => [x, y, w.min(*mw), h],
|
||||
Self::Y(mh, _) => [x, y, w, h.min(*mh)],
|
||||
Self::XY(mw, mh, _) => [x, y, w.min(*mw), h.min(*mh)],
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Min<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Min<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c } }
|
||||
}
|
||||
impl<U: Copy, A> Min<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 } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Min<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Min<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let [x, y, w, h] = self.inner().layout(area).xywh();
|
||||
match self {
|
||||
Self::X(mw, _) => [x, y, w.max(*mw), h],
|
||||
Self::Y(mh, _) => [x, y, w, h.max(*mh)],
|
||||
Self::XY(mw, mh, _) => [x, y, w.max(*mw), h.max(*mh)],
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Expand<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Expand<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c } }
|
||||
}
|
||||
impl<U: Copy + Default, A> Expand<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 } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Expand<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Expand<O::Unit, T> {
|
||||
fn w (&self, to: O::Area) -> O::Unit { self.inner().w(to).plus(self.dx().unwrap_or_default()) }
|
||||
fn h (&self, to: O::Area) -> O::Unit { self.inner().w(to).plus(self.dy().unwrap_or_default()) }
|
||||
}
|
||||
|
||||
pub enum Shrink<U, A> { X(U, A), Y(U, A), XY(U, U, A), }
|
||||
impl<U, A> Shrink<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A { match self { Self::X(_, c) | Self::Y(_, c) | Self::XY(_, _, c) => c } }
|
||||
}
|
||||
impl<U: Copy, A> Shrink<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 } }
|
||||
}
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Shrink<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Shrink<E::Unit, T> {
|
||||
fn layout (&self, to: E::Area) -> E::Area {
|
||||
let area = self.inner().layout(to);
|
||||
let dx = self.dx().unwrap_or_default();
|
||||
let dy = self.dy().unwrap_or_default();
|
||||
[area.x(), area.y(), area.w().minus(dx), area.h().minus(dy)].into()
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,9 @@
|
|||
#![feature(const_precise_live_drops)]
|
||||
#![feature(type_changing_struct_update)]
|
||||
#![feature(anonymous_lifetime_in_impl_trait)]
|
||||
#![feature(const_option_ops)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_default)]
|
||||
//#![feature(non_lifetime_binders)]
|
||||
|
||||
pub(crate) use self::Direction::*;
|
||||
|
|
@ -25,7 +28,7 @@ pub trait Out: Send + Sync + Sized {
|
|||
type Area: Area<Self::Unit>;
|
||||
|
||||
/// Render drawable in area specified by `T::layout(self.area())`
|
||||
#[inline] fn place <'t, T: Draw<Self> + Layout<Self> + ?Sized> (
|
||||
#[inline] fn place <'t, T: Content<Self> + ?Sized> (
|
||||
&mut self, content: &'t T
|
||||
) {
|
||||
self.place_at(content.layout(self.area()), content)
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ macro_rules! test_op_transform {
|
|||
h in u16::MIN..u16::MAX,
|
||||
) {
|
||||
if let Some(op) = match (op_x, op_y) {
|
||||
(Some(x), Some(y)) => Some($Op::xy(x, y, content)),
|
||||
(Some(x), None) => Some($Op::x(x, content)),
|
||||
(Some(x), Some(y)) => Some($Op::XY(x, y, content)),
|
||||
(Some(x), None) => Some($Op::X(x, content)),
|
||||
(None, Some(y)) => Some($Op::y(y, content)),
|
||||
_ => None
|
||||
} {
|
||||
|
|
@ -104,8 +104,7 @@ test_op_transform!(proptest_op_push, Push);
|
|||
test_op_transform!(proptest_op_pull, Pull);
|
||||
test_op_transform!(proptest_op_shrink, Shrink);
|
||||
test_op_transform!(proptest_op_expand, Expand);
|
||||
test_op_transform!(proptest_op_margin, Margin);
|
||||
test_op_transform!(proptest_op_padding, Padding);
|
||||
test_op_transform!(proptest_op_padding, Pad);
|
||||
|
||||
proptest! {
|
||||
#[test] fn proptest_op_bsp (
|
||||
|
|
|
|||
|
|
@ -76,6 +76,6 @@ impl<E: Out> Measure<E> {
|
|||
format!("{}x{}", self.w(), self.h()).into()
|
||||
}
|
||||
pub fn of <T: Draw<E>> (&self, item: T) -> Bsp<Fill<&Self>, T> {
|
||||
Bsp::b(Fill::xy(self), item)
|
||||
Bsp::b(Fill::XY(self), item)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +1,19 @@
|
|||
use crate::*;
|
||||
|
||||
/// Lazily-evaluated [Draw]able.
|
||||
pub struct Lazy<E, T, F>(PhantomData<(E, T)>, F);
|
||||
impl<E: Out, T: Draw<E> + Layout<E>, F: Fn()->T> Lazy<E, T, F> {
|
||||
pub const fn new (thunk: F) -> Self {
|
||||
Self(PhantomData, thunk)
|
||||
}
|
||||
}
|
||||
impl<E: Out, T: Draw<E> + Layout<E>, F: Fn()->T> Content<E> for Lazy<E, T, F> {
|
||||
fn content (&self) -> impl Draw<E> + Layout<E> + '_ {
|
||||
(self.1)()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Thunk<E: Out, F: Fn(&mut E)>(PhantomData<E>, F);
|
||||
impl<E: Out, F: Fn(&mut E)> Thunk<E, F> {
|
||||
pub const fn new (draw: F) -> Self { Self(PhantomData, draw) }
|
||||
}
|
||||
impl<E: Out, F: Fn(&mut E)> Draw<E> for Thunk<E, F> {
|
||||
fn draw (&self, to: &mut E) { (self.1)(to) }
|
||||
}
|
||||
impl<E: Out, F: Fn(&mut E)> Layout<E> for Thunk<E, F> {
|
||||
fn layout (&self, to: E::Area) -> E::Area { to }
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)] pub struct Memo<T, U> {
|
||||
pub value: T,
|
||||
pub view: Arc<RwLock<U>>
|
||||
pub struct Lazy<O, T, F>(F, PhantomData<(O, T)>);
|
||||
impl<O: Out, T: Content<O>, F: Fn()->T> Lazy<O, T, F> { pub const fn new (thunk: F) -> Self { Self(thunk, PhantomData) } }
|
||||
|
||||
pub struct Thunk<O: Out, F: Fn(&mut O)>(PhantomData<O>, F);
|
||||
impl<O: Out, F: Fn(&mut O)> Thunk<O, F> { pub const fn new (draw: F) -> Self { Self(PhantomData, draw) } }
|
||||
impl<O: Out, F: Fn(&mut O)> Layout<O> for Thunk<O, F> {}
|
||||
impl<O: Out, F: Fn(&mut O)> Draw<O> for Thunk<O, F> {
|
||||
fn draw (&self, to: &mut O) { (self.1)(to) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)] pub struct Memo<T, U> { pub value: T, pub view: Arc<RwLock<U>> }
|
||||
impl<T: PartialEq, U> Memo<T, U> {
|
||||
pub fn new (value: T, view: U) -> Self {
|
||||
Self { value, view: Arc::new(view.into()) }
|
||||
}
|
||||
pub fn update <R> (
|
||||
&mut self,
|
||||
newval: T,
|
||||
draw: impl Fn(&mut U, &T, &T)->R
|
||||
) -> Option<R> {
|
||||
pub fn new (value: T, view: U) -> Self { Self { value, view: Arc::new(view.into()) } }
|
||||
pub fn update <R> (&mut self, newval: T, draw: impl Fn(&mut U, &T, &T)->R) -> Option<R> {
|
||||
if newval != self.value {
|
||||
let result = draw(&mut*self.view.write().unwrap(), &newval, &self.value);
|
||||
self.value = newval;
|
||||
|
|
@ -48,6 +24,4 @@ impl<T: PartialEq, U> Memo<T, U> {
|
|||
}
|
||||
|
||||
/// Clear a pre-allocated buffer, then write into it.
|
||||
#[macro_export] macro_rules! rewrite {
|
||||
($buf:ident, $($rest:tt)*) => { |$buf,_,_|{ $buf.clear(); write!($buf, $($rest)*) } }
|
||||
}
|
||||
#[macro_export] macro_rules! rewrite { ($buf:ident, $($rest:tt)*) => { |$buf,_,_|{ $buf.clear(); write!($buf, $($rest)*) } } }
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ pub fn evaluate_output_expression <'a, O: Out + 'a, S> (
|
|||
}
|
||||
}),
|
||||
|
||||
Some("align") => output.place(&{
|
||||
Some("align") => output.place(&{
|
||||
let a = Thunk::new(move|output: &mut O|state.view(output, &arg0).unwrap());
|
||||
match frags.next() {
|
||||
Some("n") => Align::n(a),
|
||||
|
|
@ -81,55 +81,65 @@ pub fn evaluate_output_expression <'a, O: Out + 'a, S> (
|
|||
}
|
||||
}),
|
||||
|
||||
Some("fill") => output.place(&{
|
||||
Some("fill") => output.place(&{
|
||||
let a = Thunk::new(move|output: &mut O|state.view(output, &arg0).unwrap());
|
||||
match frags.next() {
|
||||
Some("x") => Fill::X(a),
|
||||
Some("y") => Fill::Y(a),
|
||||
Some("xy") => Fill::XY(a),
|
||||
Some("xy") | None => Fill::XY(a),
|
||||
Some("x") => Fill::X(a),
|
||||
Some("y") => Fill::Y(a),
|
||||
frag => unimplemented!("fill/{frag:?}")
|
||||
}
|
||||
}),
|
||||
|
||||
Some("fixed") => output.place(&{
|
||||
Some("fixed") => output.place(&{
|
||||
let axis = frags.next();
|
||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") => arg2, _ => panic!() };
|
||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") };
|
||||
let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap());
|
||||
match axis {
|
||||
Some("x") => Fixed::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Fixed::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("xy") => Fixed::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("xy") | None => Fixed::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("x") => Fixed::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Fixed::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
frag => unimplemented!("fixed/{frag:?} ({expr:?}) ({head:?}) ({:?})",
|
||||
head.src()?.unwrap_or_default().split("/").next())
|
||||
}
|
||||
}),
|
||||
|
||||
Some("min") => output.place(&{
|
||||
let c = match frags.next() {
|
||||
Some("x") | Some("y") => arg1, Some("xy") => arg2, _ => panic!()
|
||||
};
|
||||
let cb = Thunk::new(move|output: &mut O|state.view(output, &c).unwrap());
|
||||
match frags.next() {
|
||||
Some("x") => Min::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Min::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("xy") => Min::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("min") => output.place(&{
|
||||
let axis = frags.next();
|
||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") };
|
||||
let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap());
|
||||
match axis {
|
||||
Some("xy") | None => Min::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("x") => Min::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Min::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
frag => unimplemented!("min/{frag:?}")
|
||||
}
|
||||
}),
|
||||
|
||||
Some("max") => output.place(&{
|
||||
let c = match frags.next() {
|
||||
Some("x") | Some("y") => arg1, Some("xy") => arg2, _ => panic!()
|
||||
};
|
||||
let cb = Thunk::new(move|output: &mut O|state.view(output, &c).unwrap());
|
||||
match frags.next() {
|
||||
Some("x") => Max::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Max::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("xy") => Max::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("max") => output.place(&{
|
||||
let axis = frags.next();
|
||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") };
|
||||
let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap());
|
||||
match axis {
|
||||
Some("xy") | None => Max::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("x") => Max::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Max::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
frag => unimplemented!("max/{frag:?}")
|
||||
}
|
||||
}),
|
||||
|
||||
Some("push") => output.place(&{
|
||||
let axis = frags.next();
|
||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") };
|
||||
let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap());
|
||||
match axis {
|
||||
Some("xy") | None => Push::XY(state.from(arg0?)?.unwrap(), state.from(arg1?)?.unwrap(), cb),
|
||||
Some("x") => Push::X(state.from(arg0?)?.unwrap(), cb),
|
||||
Some("y") => Push::Y(state.from(arg0?)?.unwrap(), cb),
|
||||
frag => unimplemented!("push/{frag:?}")
|
||||
}
|
||||
}),
|
||||
|
||||
_ => return Ok(false)
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,25 +1,11 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct FieldH<Theme, Label, Value>(pub Theme, pub Label, pub Value);
|
||||
impl<O: Out, T, L: Draw<O>, V: Draw<O>> Layout<O> for FieldH<T, L, V> where Self: Content<O> {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
self.content().layout(to)
|
||||
}
|
||||
}
|
||||
impl<O: Out, T, L: Draw<O>, V: Draw<O>> Draw<O> for FieldH<T, L, V> where Self: Content<O> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
self.content().draw(to)
|
||||
}
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> HasContent<O> for FieldH<T, L, V> {
|
||||
fn content (&self) -> impl Content<O> { Bsp::e(&self.1, &self.2) }
|
||||
}
|
||||
|
||||
pub struct FieldV<Theme, Label, Value>(pub Theme, pub Label, pub Value);
|
||||
impl<O: Out, T, L: Draw<O>, V: Draw<O>> Layout<O> for FieldV<T, L, V> where Self: Content<O> {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
self.content().layout(to)
|
||||
}
|
||||
}
|
||||
impl<O: Out, T, L: Draw<O>, V: Draw<O>> Draw<O> for FieldV<T, L, V> where Self: Content<O> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
self.content().draw(to)
|
||||
}
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> HasContent<O> for FieldV<T, L, V> {
|
||||
fn content (&self) -> impl Content<O> { Bsp::s(&self.1, &self.2) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue