mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
the wild Layout trait appears
This commit is contained in:
parent
7c652135ad
commit
d37bd3e0c5
7 changed files with 576 additions and 595 deletions
|
|
@ -46,13 +46,13 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
|||
fn area_mut (&mut self) -> &mut [u16;4] {
|
||||
&mut self.0
|
||||
}
|
||||
fn render_in (&mut self, _: [u16;4], _: &dyn Render<TestEngine>) -> Usually<()> {
|
||||
fn render_in (&mut self, _: [u16;4], _: &impl Render<TestEngine>) -> Usually<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Render<TestEngine> for String {
|
||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||
Ok(Some([self.len() as u16, 1]))
|
||||
fn render (&self, to: &mut TestOutput) {
|
||||
to.area_mut().set_w(self.len() as u16);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -62,9 +62,9 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
|||
use crate::tui::*;
|
||||
use std::sync::{Arc, RwLock};
|
||||
struct TestComponent(String);
|
||||
impl Content<Tui> for TestComponent {
|
||||
fn content (&self) -> Option<impl Render<Tui>> {
|
||||
Some(&self.0)
|
||||
impl Layout<Tui> for TestComponent {
|
||||
fn layout (&self) -> Option<impl Render<Tui>> {
|
||||
Some(self.0.as_str())
|
||||
}
|
||||
}
|
||||
impl Handle<Tui> for TestComponent {
|
||||
|
|
|
|||
|
|
@ -7,158 +7,212 @@ pub trait Output<E: Engine> {
|
|||
fn area (&self) -> E::Area;
|
||||
/// Mutable pointer to area
|
||||
fn area_mut (&mut self) -> &mut E::Area;
|
||||
/// Render widget in area
|
||||
///// Render widget in area
|
||||
fn render_in (&mut self, area: E::Area, widget: &impl Render<E>) -> Usually<()>;
|
||||
|
||||
#[inline] fn x (&self) -> E::Unit { self.area().x() }
|
||||
#[inline] fn y (&self) -> E::Unit { self.area().y() }
|
||||
#[inline] fn w (&self) -> E::Unit { self.area().w() }
|
||||
#[inline] fn h (&self) -> E::Unit { self.area().h() }
|
||||
}
|
||||
|
||||
/// Something that can be represented by a renderable component.
|
||||
pub trait Content<E: Engine>: Send + Sync {
|
||||
fn content (&self) -> Option<impl Render<E>>;
|
||||
}
|
||||
impl<E: Engine, C: Content<E>> Content<E> for &C {
|
||||
fn content (&self) -> Option<impl Render<E>> {
|
||||
(*self).content()
|
||||
pub trait Layout<E: Engine>: Send + Sync {
|
||||
fn layout (&self) -> Option<impl Render<E>> {
|
||||
None::<()>
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that writes to an [Output].
|
||||
impl<E: Engine> Layout<E> for () {}
|
||||
|
||||
impl<E: Engine, L: Layout<E>> Layout<E> for &L {}
|
||||
|
||||
pub trait Render<E: Engine>: Send + Sync {
|
||||
/// Minimum size to use
|
||||
fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
||||
Ok(None)
|
||||
}
|
||||
/// Draw to output render target
|
||||
fn render (&self, _: &mut E::Output) -> Usually<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn render (&self, _: &mut E::Output);
|
||||
}
|
||||
impl<E: Engine> Render<E> for &dyn Render<E> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
||||
}
|
||||
impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
||||
}
|
||||
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
if let Some(content) = self {
|
||||
content.min_size(to)
|
||||
} else {
|
||||
Ok(None)
|
||||
|
||||
impl<E: Engine, L: Layout<E>> Render<E> for L {
|
||||
fn render (&self, to: &mut E::Output) {
|
||||
if let Some(content) = self.layout() {
|
||||
content.render(to)
|
||||
}
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
if let Some(content) = self {
|
||||
content.render(to)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Define custom content for a struct.
|
||||
///
|
||||
/// This code wires the `Content` and `Render` traits together,
|
||||
/// since the only way to have the cake and eat it too is by
|
||||
/// implementing both traits for a given renderable.
|
||||
#[macro_export] macro_rules! render {
|
||||
//impl<E: Engine, L: Layout<E>> Layout<E> for &L {}
|
||||
|
||||
// Implement from [Content] for all [Engine]s
|
||||
(|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => {
|
||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
fn content (&$self) -> Option<impl Render<$E>> { Some($cb) }
|
||||
}
|
||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.content().unwrap().min_size(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
self.content().unwrap().render(to)
|
||||
}
|
||||
}
|
||||
};
|
||||
///// Something that can be represented by a renderable component.
|
||||
//pub trait Content<E: Engine>: Send + Sync {
|
||||
//fn content (&self) -> Option<impl Render<E>>;
|
||||
//}
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for &C {
|
||||
//fn content (&self) -> Option<impl Render<E>> {
|
||||
//(*self).content()
|
||||
//}
|
||||
//}
|
||||
|
||||
// Implement from [min_size] and [render] callbacks for all engines
|
||||
($Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?
|
||||
|$self1:ident, $to1:ident|$min_size:expr,
|
||||
|$self2:ident, $to2:ident|$render:expr) =>
|
||||
{
|
||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
fn content (&self) -> Option<impl Render<E>> { Some(self) }
|
||||
}
|
||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> { $min_size }
|
||||
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> { $render }
|
||||
}
|
||||
};
|
||||
///// Something that writes to an [Output].
|
||||
//pub trait Render<E: Engine>: Send + Sync {
|
||||
///// Minimum size to use
|
||||
//fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
||||
//Ok(None)
|
||||
//}
|
||||
///// Draw to output render target
|
||||
//fn render (&self, _: &mut E::Output) -> Usually<()> {
|
||||
//Ok(())
|
||||
//}
|
||||
//}
|
||||
//impl<E: Engine> Render<E> for &dyn Render<E> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
||||
//}
|
||||
//impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
||||
//}
|
||||
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//if let Some(content) = self {
|
||||
//content.min_size(to)
|
||||
//} else {
|
||||
//Ok(None)
|
||||
//}
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//if let Some(content) = self {
|
||||
//content.render(to)?;
|
||||
//}
|
||||
//Ok(())
|
||||
//}
|
||||
//}
|
||||
|
||||
// Implement from [Content] for a particular [Engine]
|
||||
(<$E:ty>|$self:ident:$Struct:ident$(<
|
||||
$($($L:lifetime),+)?
|
||||
$($($T:ident$(:$U:path)?),+)?
|
||||
>)?|$cb:expr) => {
|
||||
impl $(<
|
||||
$($($L),+)?
|
||||
$($($T$(:$U)?),+)?
|
||||
>)? Content<$E> for $Struct $(<
|
||||
$($($L),+)?
|
||||
$($($T),+)?
|
||||
>)? {
|
||||
fn content (&$self) -> Option<impl Render<$E>> {
|
||||
Some($cb)
|
||||
}
|
||||
}
|
||||
impl $(<
|
||||
$($($L),+)?
|
||||
$($($T$(:$U)?),+)?
|
||||
>)? Render<$E> for $Struct $(<
|
||||
$($($L),+)?
|
||||
$($($T),+)?
|
||||
>)? {
|
||||
fn min_size (&self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
||||
self.content().map(|content|content.min_size(to)).unwrap_or(Ok(None))
|
||||
}
|
||||
fn render (&self, to: &mut <$E as Engine>::Output) -> Usually<()> {
|
||||
self.content().map(|content|content.render(to)).unwrap_or(Ok(()))
|
||||
}
|
||||
}
|
||||
};
|
||||
///// Define custom content for a struct.
|
||||
/////
|
||||
///// This code wires the `Content` and `Render` traits together,
|
||||
///// since the only way to have the cake and eat it too is by
|
||||
///// implementing both traits for a given renderable.
|
||||
//#[macro_export] macro_rules! render {
|
||||
|
||||
// Implement from [min_size] and [render] callbacks for a particular [Engine]
|
||||
(<$E:ty>($self:ident:$Struct:ident$(<$($L:lifetime),*$(,$T:ident$(:$U:path)?)*$(,)?>)?)
|
||||
|$to1:ident|$min_size:expr, |$to2:ident|$render:expr) =>
|
||||
{
|
||||
impl $(<
|
||||
$($L),* $($($T$(:$U)?),+)?
|
||||
>)? Content<$E> for $Struct $(<
|
||||
$($L),* $($($T),+)?
|
||||
>)? {
|
||||
fn content (&self) -> Option<impl Render<$E>> { Some(self) }
|
||||
}
|
||||
impl $(<
|
||||
$($L),* $($($T$(:$U)?),+)?
|
||||
>)? Render<$E> for $Struct $(<
|
||||
$($L),* $($($T),+)?
|
||||
>)? {
|
||||
fn min_size (&$self, $to1: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
||||
$min_size
|
||||
}
|
||||
fn render (&$self, $to2: &mut <$E as Engine>::Output) -> Usually<()> {
|
||||
$render
|
||||
}
|
||||
}
|
||||
}
|
||||
//// Implement from [Content] for all [Engine]s
|
||||
//(|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => {
|
||||
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
//fn content (&$self) -> Option<impl Render<$E>> { Some($cb) }
|
||||
//}
|
||||
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//self.content().unwrap().min_size(to)
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//self.content().unwrap().render(to)
|
||||
//}
|
||||
//}
|
||||
//};
|
||||
|
||||
}
|
||||
//// Implement from [min_size] and [render] callbacks for all engines
|
||||
//($Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?
|
||||
//|$self1:ident, $to1:ident|$min_size:expr,
|
||||
//|$self2:ident, $to2:ident|$render:expr) =>
|
||||
//{
|
||||
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
//fn content (&self) -> Option<impl Render<E>> { Some(self) }
|
||||
//}
|
||||
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||
//fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> { $min_size }
|
||||
//fn render (&$self2, $to2: &mut E::Output) -> Usually<()> { $render }
|
||||
//}
|
||||
//};
|
||||
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for &mut C {}
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for Option<C> {}
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for Arc<C> {}
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for Mutex<C> {}
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for RwLock<C> {}
|
||||
//// Implement from [Content] for a particular [Engine]
|
||||
//(<$E:ty>|$self:ident:$Struct:ident$(<
|
||||
//$($($L:lifetime),+)?
|
||||
//$($($T:ident$(:$U:path)?),+)?
|
||||
//>)?|$cb:expr) => {
|
||||
//impl $(<
|
||||
//$($($L),+)?
|
||||
//$($($T$(:$U)?),+)?
|
||||
//>)? Content<$E> for $Struct $(<
|
||||
//$($($L),+)?
|
||||
//$($($T),+)?
|
||||
//>)? {
|
||||
//fn content (&$self) -> Option<impl Render<$E>> {
|
||||
//Some($cb)
|
||||
//}
|
||||
//}
|
||||
//impl $(<
|
||||
//$($($L),+)?
|
||||
//$($($T$(:$U)?),+)?
|
||||
//>)? Render<$E> for $Struct $(<
|
||||
//$($($L),+)?
|
||||
//$($($T),+)?
|
||||
//>)? {
|
||||
//fn min_size (&self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
||||
//self.content().map(|content|content.min_size(to)).unwrap_or(Ok(None))
|
||||
//}
|
||||
//fn render (&self, to: &mut <$E as Engine>::Output) -> Usually<()> {
|
||||
//self.content().map(|content|content.render(to)).unwrap_or(Ok(()))
|
||||
//}
|
||||
//}
|
||||
//};
|
||||
|
||||
//impl<E: Engine, C: Content<E>> Render<E> for C {}
|
||||
//// Implement from [min_size] and [render] callbacks for a particular [Engine]
|
||||
//(<$E:ty>($self:ident:$Struct:ident$(<$($L:lifetime),*$(,$T:ident$(:$U:path)?)*$(,)?>)?)
|
||||
//|$to1:ident|$min_size:expr, |$to2:ident|$render:expr) =>
|
||||
//{
|
||||
//impl $(<
|
||||
//$($L),* $($($T$(:$U)?),+)?
|
||||
//>)? Content<$E> for $Struct $(<
|
||||
//$($L),* $($($T),+)?
|
||||
//>)? {
|
||||
//fn content (&self) -> Option<impl Render<$E>> { Some(self) }
|
||||
//}
|
||||
//impl $(<
|
||||
//$($L),* $($($T$(:$U)?),+)?
|
||||
//>)? Render<$E> for $Struct $(<
|
||||
//$($L),* $($($T),+)?
|
||||
//>)? {
|
||||
//fn min_size (&$self, $to1: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
||||
//$min_size
|
||||
//}
|
||||
//fn render (&$self, $to2: &mut <$E as Engine>::Output) -> Usually<()> {
|
||||
//$render
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
//}
|
||||
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for &mut C {}
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for Option<C> {}
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for Arc<C> {}
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for Mutex<C> {}
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for RwLock<C> {}
|
||||
|
||||
////impl<E: Engine, C: Content<E>> Render<E> for C {}
|
||||
|
||||
////impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||
/////// Minimum size to use
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////self.content().map(|content|content.min_size(to))
|
||||
////.unwrap_or(Ok(None))
|
||||
////}
|
||||
/////// Draw to output render target
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////self.content().map(|content|content.render(to))
|
||||
////.unwrap_or(Ok(()))
|
||||
////}
|
||||
////}
|
||||
|
||||
//[>***
|
||||
|
||||
|
||||
//impl<E: Engine, R: Render<E> + Send + Sync> Content<E> for R {}
|
||||
|
||||
////impl<E: Engine, R: Render<E>> Content<E> for R {
|
||||
////fn content (&self) -> Option<impl Render<E>> {
|
||||
////Some(self)
|
||||
////}
|
||||
////}
|
||||
|
||||
///// All implementors of [Content] can be [Render]ed.
|
||||
//impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||
///// Minimum size to use
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
|
|
@ -172,65 +226,20 @@ impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
|||
//}
|
||||
//}
|
||||
|
||||
/****
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for &C {
|
||||
////fn content (&self) -> Option<impl Render<E>> {
|
||||
////Some(self)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine, C: Content<E>> Content<E> for Option<C> {
|
||||
////fn content (&self) -> Option<impl Render<E>> {
|
||||
////Some(self)
|
||||
////}
|
||||
////}
|
||||
|
||||
|
||||
impl<E: Engine, R: Render<E> + Send + Sync> Content<E> for R {}
|
||||
|
||||
//impl<E: Engine, R: Render<E>> Content<E> for R {
|
||||
//fn content (&self) -> Option<impl Render<E>> {
|
||||
//Some(self)
|
||||
//}
|
||||
//}
|
||||
|
||||
/// All implementors of [Content] can be [Render]ed.
|
||||
impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||
/// Minimum size to use
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.content().map(|content|content.min_size(to))
|
||||
.unwrap_or(Ok(None))
|
||||
}
|
||||
/// Draw to output render target
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
self.content().map(|content|content.render(to))
|
||||
.unwrap_or(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for &C {
|
||||
//fn content (&self) -> Option<impl Render<E>> {
|
||||
//Some(self)
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<E: Engine, C: Content<E>> Content<E> for Option<C> {
|
||||
//fn content (&self) -> Option<impl Render<E>> {
|
||||
//Some(self)
|
||||
//}
|
||||
//}
|
||||
|
||||
|
||||
impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
(*self).min_size(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
(*self).render(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.map(|content|content.min_size(to))
|
||||
.unwrap_or(Ok(None))
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
self.map(|content|content.render(to))
|
||||
.unwrap_or(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
//impl<E: Engine> Render<E> for &dyn Render<E> {
|
||||
//impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//(*self).min_size(to)
|
||||
//}
|
||||
|
|
@ -239,124 +248,144 @@ impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
|||
//}
|
||||
//}
|
||||
|
||||
//impl<E: Engine> Render<E> for &mut dyn Render<E> {
|
||||
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//(*self).min_size(to)
|
||||
//self.map(|content|content.min_size(to))
|
||||
//.unwrap_or(Ok(None))
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//(*self).render(to)
|
||||
//self.map(|content|content.render(to))
|
||||
//.unwrap_or(Ok(()))
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<E: Engine> Render<E> for Box<dyn Render<E> + '_> {
|
||||
////impl<E: Engine> Render<E> for &dyn Render<E> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////(*self).min_size(to)
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////(*self).render(to)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine> Render<E> for &mut dyn Render<E> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////(*self).min_size(to)
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////(*self).render(to)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine> Render<E> for Box<dyn Render<E> + '_> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////(**self).min_size(to)
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////(**self).render(to)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine, W: Render<E>> Render<E> for Arc<W> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////self.as_ref().min_size(to)
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////self.as_ref().render(to)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine, W: Render<E>> Render<E> for Mutex<W> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////self.lock().unwrap().min_size(to)
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////self.lock().unwrap().render(to)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine, W: Render<E>> Render<E> for RwLock<W> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////self.read().unwrap().min_size(to)
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////self.read().unwrap().render(to)
|
||||
////}
|
||||
////}
|
||||
|
||||
////impl<E: Engine, W: Render<E>> Render<E> for Option<W> {
|
||||
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
////Ok(self.as_ref().map(|widget|widget.min_size(to)).transpose()?.flatten())
|
||||
////}
|
||||
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
////self.as_ref().map(|widget|widget.render(to)).unwrap_or(Ok(()))
|
||||
////}
|
||||
////}
|
||||
|
||||
///// Cast to dynamic pointer
|
||||
//pub fn widget <E, T> (w: &T) -> &dyn Render<E>
|
||||
//where E: Engine, T: Render<E>
|
||||
//{
|
||||
//w as &dyn Render<E>
|
||||
//}
|
||||
|
||||
///// Ad-hoc widget with custom rendering.
|
||||
//pub fn render <E, F> (render: F) -> impl Render<E>
|
||||
//where E: Engine, F: Fn(&mut E::Output)->Usually<()>+Send+Sync
|
||||
//{
|
||||
//Widget::new(|_|Ok(Some([0.into(),0.into()].into())), render)
|
||||
//}
|
||||
|
||||
///// A custom [Render] defined by passing layout and render closures in place.
|
||||
//pub struct Widget<
|
||||
//E: Engine,
|
||||
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||
//>(L, R, PhantomData<E>);
|
||||
|
||||
//impl<
|
||||
//E: Engine,
|
||||
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||
//> Widget<E, L, R> {
|
||||
//pub fn new (layout: L, render: R) -> Self {
|
||||
//Self(layout, render, Default::default())
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<
|
||||
//E: Engine,
|
||||
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||
//> Render<E> for Widget<E, L, R> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//(**self).min_size(to)
|
||||
//self.0(to)
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//(**self).render(to)
|
||||
//self.1(to)
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<E: Engine, W: Render<E>> Render<E> for Arc<W> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//self.as_ref().min_size(to)
|
||||
///// Has static methods for conditional rendering,
|
||||
///// in unary and binary forms.
|
||||
//pub struct Cond;
|
||||
|
||||
//impl Cond {
|
||||
///// Render `item` when `cond` is true.
|
||||
//pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
|
||||
//When(cond, item, Default::default())
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//self.as_ref().render(to)
|
||||
///// Render `item` if `cond` is true, otherwise render `other`.
|
||||
//pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
|
||||
//Either(cond, item, other, Default::default())
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<E: Engine, W: Render<E>> Render<E> for Mutex<W> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//self.lock().unwrap().min_size(to)
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//self.lock().unwrap().render(to)
|
||||
//}
|
||||
//}
|
||||
///// Renders `self.1` when `self.0` is true.
|
||||
//pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
|
||||
|
||||
//impl<E: Engine, W: Render<E>> Render<E> for RwLock<W> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//self.read().unwrap().min_size(to)
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//self.read().unwrap().render(to)
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<E: Engine, W: Render<E>> Render<E> for Option<W> {
|
||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
//Ok(self.as_ref().map(|widget|widget.min_size(to)).transpose()?.flatten())
|
||||
//}
|
||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
//self.as_ref().map(|widget|widget.render(to)).unwrap_or(Ok(()))
|
||||
//}
|
||||
//}
|
||||
|
||||
/// Cast to dynamic pointer
|
||||
pub fn widget <E, T> (w: &T) -> &dyn Render<E>
|
||||
where E: Engine, T: Render<E>
|
||||
{
|
||||
w as &dyn Render<E>
|
||||
}
|
||||
|
||||
/// Ad-hoc widget with custom rendering.
|
||||
pub fn render <E, F> (render: F) -> impl Render<E>
|
||||
where E: Engine, F: Fn(&mut E::Output)->Usually<()>+Send+Sync
|
||||
{
|
||||
Widget::new(|_|Ok(Some([0.into(),0.into()].into())), render)
|
||||
}
|
||||
|
||||
/// A custom [Render] defined by passing layout and render closures in place.
|
||||
pub struct Widget<
|
||||
E: Engine,
|
||||
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||
>(L, R, PhantomData<E>);
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||
> Widget<E, L, R> {
|
||||
pub fn new (layout: L, render: R) -> Self {
|
||||
Self(layout, render, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||
> Render<E> for Widget<E, L, R> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
self.0(to)
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
self.1(to)
|
||||
}
|
||||
}
|
||||
|
||||
/// Has static methods for conditional rendering,
|
||||
/// in unary and binary forms.
|
||||
pub struct Cond;
|
||||
|
||||
impl Cond {
|
||||
/// Render `item` when `cond` is true.
|
||||
pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
|
||||
When(cond, item, Default::default())
|
||||
}
|
||||
/// Render `item` if `cond` is true, otherwise render `other`.
|
||||
pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
|
||||
Either(cond, item, other, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders `self.1` when `self.0` is true.
|
||||
pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
|
||||
|
||||
/// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
|
||||
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
|
||||
///// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
|
||||
//pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
|
||||
|
||||
|
||||
**/
|
||||
//**/
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ impl Tui {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait TuiRun<R: Render<Tui> + Handle<Tui> + Sized + 'static> {
|
||||
pub trait TuiRun<R: Layout<Tui> + Handle<Tui> + Sized + 'static> {
|
||||
/// Run an app in the main loop.
|
||||
fn run (&self, state: &Arc<RwLock<R>>) -> Usually<()>;
|
||||
/// Spawn the input thread.
|
||||
|
|
@ -98,7 +98,7 @@ pub trait TuiRun<R: Render<Tui> + Handle<Tui> + Sized + 'static> {
|
|||
fn run_output (&self, state: &Arc<RwLock<R>>, sleep: Duration) -> JoinHandle<()>;
|
||||
}
|
||||
|
||||
impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
|
||||
impl<T: Layout<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
|
||||
fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()> {
|
||||
let _input_thread = self.run_input(state, Duration::from_millis(100));
|
||||
self.write().unwrap().setup()?;
|
||||
|
|
@ -151,7 +151,7 @@ impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tu
|
|||
buffer.reset();
|
||||
}
|
||||
let mut output = TuiOutput { buffer, area: [0, 0, width, height] };
|
||||
state.render(&mut output).expect("render failed");
|
||||
state.render(&mut output);
|
||||
buffer = engine.write().unwrap().flip(output.buffer, size);
|
||||
}
|
||||
std::thread::sleep(sleep);
|
||||
|
|
@ -257,7 +257,7 @@ impl Output<Tui> for TuiOutput {
|
|||
#[inline] fn render_in (&mut self, area: [u16;4], widget: &impl Render<Tui>) -> Usually<()> {
|
||||
let last = self.area();
|
||||
*self.area_mut() = area;
|
||||
widget.render(self)?;
|
||||
widget.render(self);
|
||||
*self.area_mut() = last;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -331,26 +331,14 @@ pub fn half_block (lower: bool, upper: bool) -> Option<char> {
|
|||
//impl<T: Content<Tui>> Render<Tui> for T {}
|
||||
|
||||
impl Render<Tui> for &str {
|
||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||
// TODO: line breaks
|
||||
Ok(Some([self.chars().count() as u16, 1]))
|
||||
}
|
||||
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
||||
let [x, y, ..] = to.area();
|
||||
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
|
||||
Ok(to.blit(&self, x, y, None))
|
||||
fn render (&self, to: &mut TuiOutput) {
|
||||
to.blit(self, to.area.x(), to.area.y(), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render<Tui> for String {
|
||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||
// TODO: line breaks
|
||||
Ok(Some([self.chars().count() as u16, 1]))
|
||||
}
|
||||
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
||||
let [x, y, ..] = to.area();
|
||||
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
|
||||
Ok(to.blit(&self, x, y, None))
|
||||
fn render (&self, to: &mut TuiOutput) {
|
||||
to.blit(self, to.area.x(), to.area.y(), None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
254
layout/Cargo.lock
generated
254
layout/Cargo.lock
generated
|
|
@ -41,7 +41,7 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -83,13 +83,14 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.7.1"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
|
||||
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
|
||||
dependencies = [
|
||||
"castaway",
|
||||
"cfg-if",
|
||||
"itoa",
|
||||
"rustversion",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
|
@ -108,15 +109,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.27.0"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"rustix",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
|
|
@ -131,6 +132,47 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
|
|
@ -149,6 +191,22 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.4"
|
||||
|
|
@ -179,12 +237,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "2.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||
|
||||
[[package]]
|
||||
name = "instability"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "898e106451f7335950c9cc64f8ec67b5f65698679ac67ed00619aeef14e1cf75"
|
||||
dependencies = [
|
||||
"either",
|
||||
"darling",
|
||||
"indoc",
|
||||
"pretty_assertions",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -208,6 +283,12 @@ version = "0.2.169"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
|
|
@ -250,14 +331,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -295,7 +376,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -304,6 +385,16 @@ version = "1.0.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
|
|
@ -324,22 +415,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
version = "0.26.3"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef"
|
||||
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm",
|
||||
"itertools 0.12.1",
|
||||
"indoc",
|
||||
"instability",
|
||||
"itertools",
|
||||
"lru",
|
||||
"paste",
|
||||
"stability",
|
||||
"strum",
|
||||
"unicode-segmentation",
|
||||
"unicode-truncate",
|
||||
"unicode-width",
|
||||
"unicode-width 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -357,6 +449,19 @@ version = "0.1.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.19"
|
||||
|
|
@ -411,22 +516,18 @@ version = "1.13.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "stability"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.3"
|
||||
|
|
@ -494,9 +595,9 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
||||
dependencies = [
|
||||
"itertools 0.13.0",
|
||||
"itertools",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
"unicode-width 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -505,6 +606,12 @@ version = "0.1.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
|
@ -535,11 +642,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -548,22 +655,7 @@ version = "0.59.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -572,46 +664,28 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
|
|
@ -624,50 +698,32 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
|
|
|||
|
|
@ -4,40 +4,26 @@ use crate::*;
|
|||
pub struct Cond;
|
||||
|
||||
impl Cond {
|
||||
/// Render `item` when `cond` is true.
|
||||
pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
|
||||
When(cond, item, Default::default())
|
||||
/// Show an item conditionally.
|
||||
pub fn when <E: Engine> (cond: bool, item: Box<dyn Layout<E>>) -> When<E> {
|
||||
When(cond, item)
|
||||
}
|
||||
/// Render `item` if `cond` is true, otherwise render `other`.
|
||||
pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
|
||||
Either(cond, item, other, Default::default())
|
||||
/// Show either of two items.
|
||||
pub fn either <E: Engine> (cond: bool, a: Box<dyn Layout<E>>, b: Box<dyn Layout<E>>) -> Either<E> {
|
||||
Either(cond, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders `self.1` when `self.0` is true.
|
||||
pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
|
||||
|
||||
impl<E: Engine, A: Render<E>> Render<E> for When<E, A> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
let Self(cond, item, ..) = self;
|
||||
if *cond { item.min_size(to) } else { Ok(Some([0.into(), 0.into()].into())) }
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let Self(cond, item, ..) = self;
|
||||
if *cond { item.render(to) } else { Ok(()) }
|
||||
pub struct When<E>(bool, Box<dyn Layout<E>>);
|
||||
impl<E: Engine> Layout<E> for When<E> {
|
||||
fn layout (self, _: &mut E::Output) -> Option<Box<dyn Layout<E>>> {
|
||||
if self.0 { Some(self.1) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
|
||||
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
|
||||
|
||||
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Either<E, A, B> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
let Self(cond, item, other, ..) = self;
|
||||
if *cond { item.min_size(to) } else { other.min_size(to) }
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
let Self(cond, item, other, ..) = self;
|
||||
if *cond { item.render(to) } else { other.render(to) }
|
||||
pub struct Either<E: Engine>(bool, Box<dyn Layout<E>>, Box<dyn Layout<E>>);
|
||||
impl<E: Engine> Layout<E> for Either<E> {
|
||||
fn layout (self, _: &mut E::Output) -> Option<Box<dyn Layout<E>>> {
|
||||
Some(if self.0 { self.1 } else { self.2 })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use crate::*;
|
||||
use std::sync::{Arc, atomic::{AtomicUsize, Ordering::Relaxed}};
|
||||
|
||||
// TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small
|
||||
|
||||
impl Direction {
|
||||
pub fn is_north (&self) -> bool { matches!(self, Self::North) }
|
||||
pub fn is_south (&self) -> bool { matches!(self, Self::South) }
|
||||
|
|
@ -46,13 +48,12 @@ pub struct Measure<E: Engine> {
|
|||
pub y: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
render!(Measure<E>
|
||||
|self, layout|Ok(Some(layout)),
|
||||
|self, render|{
|
||||
self.x.store(render.area().w().into(), Relaxed);
|
||||
self.y.store(render.area().h().into(), Relaxed);
|
||||
Ok(())
|
||||
});
|
||||
impl<E: Engine> Render<E> for Measure<E> {
|
||||
fn render (&self, to: &mut E::Output) {
|
||||
self.x.store(to.area().w().into(), Relaxed);
|
||||
self.y.store(to.area().h().into(), Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Clone for Measure<E> {
|
||||
fn clone (&self) -> Self {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ macro_rules! content_enum {
|
|||
pub enum $Enum<E: Engine, T: Render<E>> {
|
||||
_Unused(PhantomData<E>), $($Variant(T)),+
|
||||
}
|
||||
impl<E: Engine, T: Render<E>> Content<E> for $Enum<E, T> {
|
||||
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||
fn content (&self) -> Option<impl Render<E>> {
|
||||
match self {
|
||||
Self::_Unused(_) => None,
|
||||
|
|
@ -25,36 +25,25 @@ macro_rules! content_enum {
|
|||
/// Defines an enum that transforms its content
|
||||
/// along either the X axis, the Y axis, or both.
|
||||
macro_rules! transform_xy {
|
||||
($Enum:ident $(
|
||||
|$self1:ident, $to1:ident|$min_size:expr,
|
||||
|$self2:ident, $to2:ident|$render:expr
|
||||
)?) => {
|
||||
(|$self:ident : $Enum:ident, $to:ident|$render:expr) => {
|
||||
content_enum!($Enum: X, Y, XY);
|
||||
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||
pub fn x (item: T) -> Self { Self::X(item) }
|
||||
pub fn y (item: T) -> Self { Self::Y(item) }
|
||||
pub fn xy (item: T) -> Self { Self::XY(item) }
|
||||
}
|
||||
$(
|
||||
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
||||
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> {
|
||||
$min_size
|
||||
}
|
||||
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> {
|
||||
$render
|
||||
}
|
||||
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
||||
fn render (&$self, $to: &mut <E as Engine>::Output) {
|
||||
$render
|
||||
}
|
||||
)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines an enum that transforms its content parametrically
|
||||
/// along either the X axis, the Y axis, or both
|
||||
macro_rules! transform_xy_unit {
|
||||
($Enum:ident $(
|
||||
|$self1:ident, $to1:ident|$min_size:expr,
|
||||
|$self2:ident, $to2:ident|$render:expr
|
||||
)?) => {
|
||||
(|$self:ident : $Enum:ident, $to:ident|$render:expr) => {
|
||||
pub enum $Enum<E: Engine, T: Render<E>> {
|
||||
X(E::Unit, T), Y(E::Unit, T), XY(E::Unit, E::Unit, T),
|
||||
}
|
||||
|
|
@ -77,151 +66,83 @@ macro_rules! transform_xy_unit {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl<E: Engine, T: Render<E>> Content<E> for $Enum<E, T> {
|
||||
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||
fn content (&self) -> Option<impl Render<E>> {
|
||||
Some(match self {
|
||||
Self::X(_, content) => content,
|
||||
Self::Y(_, content) => content,
|
||||
Self::X(_, content) => content,
|
||||
Self::Y(_, content) => content,
|
||||
Self::XY(_, _, content) => content,
|
||||
})
|
||||
}
|
||||
}
|
||||
$(
|
||||
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
||||
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> {
|
||||
$min_size
|
||||
}
|
||||
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> {
|
||||
$render
|
||||
}
|
||||
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
||||
fn render (&$self, $to: &mut E::Output) -> Usually<()> {
|
||||
$render
|
||||
}
|
||||
)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform_xy!(Fill
|
||||
|self, to|{
|
||||
let area = self.content().min_size(to.into())?;
|
||||
if let Some(area) = area {
|
||||
Ok(Some(match self {
|
||||
Self::X(_) => [to.w().into(), area.h()],
|
||||
Self::Y(_) => [area.w(), to.h().into()],
|
||||
Self::XY(_) => [to.w().into(), to.h().into()],
|
||||
_ => unreachable!(),
|
||||
}.into()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
},
|
||||
|self, to|self.content().render(to));
|
||||
transform_xy!(|self: Fill, to|todo!());
|
||||
|
||||
transform_xy_unit!(Fixed
|
||||
|self, to|{
|
||||
Ok(match self {
|
||||
Self::X(w, _) =>
|
||||
if to.w() >= *w { Some([*w, to.h()].into()) } else { None },
|
||||
Self::Y(h, _) =>
|
||||
if to.h() >= *h { Some([to.w(), *h].into()) } else { None },
|
||||
Self::XY(w, h, _)
|
||||
=> if to.w() >= *w && to.h() >= *h { Some([*w, *h].into()) } else { None },
|
||||
})
|
||||
},
|
||||
|self, to|{
|
||||
// 🡘 🡙 ←🡙→
|
||||
if let Some(size) = self.min_size(to.area().wh().into())? {
|
||||
to.render_in(to.area().clip(size).into(), &self.content())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
transform_xy_unit!(|self: Fixed, to|{
|
||||
let [x, y, w, h] = to.area().xywh();
|
||||
to.render_in(match self {
|
||||
Self::X(fw, _) => [x, y, fw, h],
|
||||
Self::Y(fh, _) => [x, y, w, fh],
|
||||
Self::XY(fw, fh, _) => [x, y, fw, fh],
|
||||
}, self.content())
|
||||
});
|
||||
|
||||
transform_xy_unit!(Shrink
|
||||
|self, to|Ok(self.content().min_size(to)?
|
||||
.map(|wh|wh.wh())
|
||||
.map(|[w, h]|[
|
||||
w.minus(self.dx()).into(),
|
||||
h.minus(self.dy()).into()
|
||||
].into())),
|
||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
||||
.transpose()?.unwrap_or(())));
|
||||
transform_xy_unit!(|self: Shrink, to|to.render_in(
|
||||
[to.x(), to.y(), to.w().minus(self.dx()), to.h().minus(self.dy())],
|
||||
self.content()));
|
||||
|
||||
transform_xy_unit!(Expand
|
||||
|self, to|Ok(self.content().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w() + w, to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h() + h],
|
||||
Self::XY(w, h, _) => [to.w() + w, to.h() + h],
|
||||
}.into())),
|
||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
||||
.transpose()?.unwrap_or(())));
|
||||
transform_xy_unit!(|self: Expand, to|to.render_in(
|
||||
[to.x(), to.y(), to.w() + self.dx(), to.h() + self.dy()],
|
||||
self.content()));
|
||||
|
||||
// TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small
|
||||
transform_xy_unit!(|self: Min, to|to.render_in(match self {
|
||||
Self::X(mw, _) => [to.x(), to.y(), to.w().max(mw), to.h()],
|
||||
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().max(mh)],
|
||||
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().max(mw), to.h().max(mh)]
|
||||
}, self.content()));
|
||||
|
||||
transform_xy_unit!(Min
|
||||
|self, to|Ok(self.content().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().max(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().max(h)],
|
||||
Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)],
|
||||
}.into())),
|
||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
||||
.transpose()?.unwrap_or(())));
|
||||
transform_xy_unit!(|self: Max, to|to.render_in(match self {
|
||||
Self::X(mw, _) => [to.x(), to.y(), to.w().min(mw), to.h()],
|
||||
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().min(mh)],
|
||||
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().min(mw), to.h().min(mh)],
|
||||
}, self.content()));
|
||||
|
||||
transform_xy_unit!(Max
|
||||
|self, to|Ok(self.content().min_size(to)?.map(|to|match *self {
|
||||
Self::X(w, _) => [to.w().min(w), to.h()],
|
||||
Self::Y(h, _) => [to.w(), to.h().min(h)],
|
||||
Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)],
|
||||
}.into())),
|
||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
||||
.transpose()?.unwrap_or(())));
|
||||
transform_xy_unit!(|self: Push, to|to.render_in(
|
||||
[to.x() + self.dx(), to.y() + self.dy(), to.w(), to.h()],
|
||||
self.content()));
|
||||
|
||||
transform_xy_unit!(Push
|
||||
|self, to|self.content().min_size(to),
|
||||
|self, to|Ok(if let Some(size) = self.min_size(to.area().wh().into())? {
|
||||
to.render_in([
|
||||
to.area().x() + self.dx(),
|
||||
to.area().y() + self.dy(),
|
||||
size.w(),
|
||||
size.h(),
|
||||
].into(), &self.content())?;
|
||||
}));
|
||||
transform_xy_unit!(|self: Pull, to|to.render_in(
|
||||
[to.x().minus(self.dx()), to.y().minus(self.dy()), to.w(), to.h()],
|
||||
self.content()));
|
||||
|
||||
transform_xy_unit!(Pull
|
||||
|self, to|self.content().min_size(to),
|
||||
|self, to|Ok(if let Some(size) = self.min_size(to.area().wh().into())? {
|
||||
to.render_in([
|
||||
to.area().x().minus(self.dx()),
|
||||
to.area().y().minus(self.dy()),
|
||||
size.w(),
|
||||
size.h(),
|
||||
].into(), &self.content())?;
|
||||
}));
|
||||
transform_xy_unit!(|self: Margin, to|{
|
||||
let dx = self.dx();
|
||||
let dy = self.dy();
|
||||
to.render_in([
|
||||
to.x().minus(dx),
|
||||
to.y().minus(dy),
|
||||
to.w() + dy + dy,
|
||||
to.h() + dy + dy,
|
||||
])
|
||||
});
|
||||
|
||||
transform_xy_unit!(Margin
|
||||
|self, to|match *self {
|
||||
Self::X(x, ref content) => Expand::x(x + x, content),
|
||||
Self::Y(y, ref content) => Expand::y(y + y, content),
|
||||
Self::XY(x, y, ref content) => Expand::xy(x + x, y + y, content),
|
||||
}.min_size(to),
|
||||
|self, to|match *self {
|
||||
Self::X(x, ref content) => Push::x(x, content),
|
||||
Self::Y(y, ref content) => Push::y(y, content),
|
||||
Self::XY(x, y, ref content) => Push::xy(x, y, content),
|
||||
}.render(to));
|
||||
|
||||
transform_xy_unit!(Padding);
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Padding<E, T> {
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
match self {
|
||||
Self::X(x, content) => Push::x(*x, Shrink::x(*x, content)),
|
||||
Self::Y(y, content) => Push::y(*y, Shrink::y(*y, content)),
|
||||
Self::XY(x, y, content) => Push::xy(*x, *y, Shrink::xy(*x, *y, content)),
|
||||
}.render(to)
|
||||
}
|
||||
}
|
||||
transform_xy_unit!(|self: Padding, to|{
|
||||
let dx = self.dx();
|
||||
let dy = self.dy();
|
||||
to.render_in([
|
||||
to.x() + dx,
|
||||
to.y() + dy,
|
||||
to.w().minus(dy + dy),
|
||||
to.h().minus(dy + dy),
|
||||
])
|
||||
});
|
||||
|
||||
content_enum!(Align: Center, X, Y, NW, N, NE, E, SE, S, SW, W);
|
||||
impl<E: Engine, T: Render<E>> Align<E, T> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue