mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: big flat pt.4: extract layout crate
This commit is contained in:
parent
cb680ab096
commit
34e731f111
21 changed files with 2125 additions and 83 deletions
|
|
@ -5,6 +5,8 @@ version = "0.2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tek_engine = { path = "./engine" }
|
tek_engine = { path = "./engine" }
|
||||||
|
tek_layout = { path = "./layout" }
|
||||||
|
|
||||||
atomic_float = "1.0.0"
|
atomic_float = "1.0.0"
|
||||||
backtrace = "0.3.72"
|
backtrace = "0.3.72"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,14 @@ pub trait Coordinate: Send + Sync + Copy
|
||||||
+ Into<usize>
|
+ Into<usize>
|
||||||
+ Into<f64>
|
+ Into<f64>
|
||||||
{
|
{
|
||||||
fn minus (self, other: Self) -> Self {
|
#[inline] fn minus (self, other: Self) -> Self {
|
||||||
if self >= other {
|
if self >= other {
|
||||||
self - other
|
self - other
|
||||||
} else {
|
} else {
|
||||||
0.into()
|
0.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn zero () -> Self {
|
#[inline] fn zero () -> Self {
|
||||||
0.into()
|
0.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,6 +65,16 @@ pub trait Size<N: Coordinate> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N: Coordinate> Size<N> for (N, N) {
|
||||||
|
#[inline] fn x (&self) -> N { self.0 }
|
||||||
|
#[inline] fn y (&self) -> N { self.1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Coordinate> Size<N> for [N;2] {
|
||||||
|
#[inline] fn x (&self) -> N { self[0] }
|
||||||
|
#[inline] fn y (&self) -> N { self[1] }
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Area<N: Coordinate>: Copy {
|
pub trait Area<N: Coordinate>: Copy {
|
||||||
fn x (&self) -> N;
|
fn x (&self) -> N;
|
||||||
fn y (&self) -> N;
|
fn y (&self) -> N;
|
||||||
|
|
@ -77,4 +87,33 @@ pub trait Area<N: Coordinate>: Copy {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline] fn wh (&self) -> [N;2] {
|
||||||
|
[self.w(), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn xywh (&self) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w(), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn clip_h (&self, h: N) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w(), self.h().min(h)]
|
||||||
|
}
|
||||||
|
#[inline] fn clip_w (&self, w: N) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w().min(w), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn clip (&self, wh: impl Size<N>) -> [N;4] {
|
||||||
|
[self.x(), self.y(), wh.w(), wh.h()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Coordinate> Area<N> for (N, N, N, N) {
|
||||||
|
#[inline] fn x (&self) -> N { self.0 }
|
||||||
|
#[inline] fn y (&self) -> N { self.1 }
|
||||||
|
#[inline] fn w (&self) -> N { self.2 }
|
||||||
|
#[inline] fn h (&self) -> N { self.3 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Coordinate> Area<N> for [N;4] {
|
||||||
|
#[inline] fn x (&self) -> N { self[0] }
|
||||||
|
#[inline] fn y (&self) -> N { self[1] }
|
||||||
|
#[inline] fn w (&self) -> N { self[2] }
|
||||||
|
#[inline] fn h (&self) -> N { self[3] }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,38 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
|
||||||
|
/// Define custom content for a struct.
|
||||||
|
#[macro_export] macro_rules! render {
|
||||||
|
|
||||||
|
// Implement for all engines
|
||||||
|
(|$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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implement for a specific 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// Write content to output buffer.
|
/// Write content to output buffer.
|
||||||
pub trait Render<E: Engine>: Send + Sync {
|
pub trait Render<E: Engine>: Send + Sync {
|
||||||
/// Minimum size to use
|
/// Minimum size to use
|
||||||
|
|
@ -18,18 +50,18 @@ pub trait Content<E: Engine>: Send + Sync {
|
||||||
fn content (&self) -> Option<impl Render<E>>;
|
fn content (&self) -> Option<impl Render<E>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine, C: Content<E>> Render<E> for C {
|
//impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||||
/// Minimum size to use
|
///// Minimum size to use
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
self.content().map(|content|content.min_size(to))
|
//self.content().map(|content|content.min_size(to))
|
||||||
.unwrap_or(Ok(None))
|
//.unwrap_or(Ok(None))
|
||||||
}
|
//}
|
||||||
/// Draw to output render target
|
///// Draw to output render target
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
self.content().map(|content|content.render(to))
|
//self.content().map(|content|content.render(to))
|
||||||
.unwrap_or(Ok(()))
|
//.unwrap_or(Ok(()))
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// Rendering target
|
/// Rendering target
|
||||||
pub trait Output<E: Engine> {
|
pub trait Output<E: Engine> {
|
||||||
|
|
@ -44,9 +76,9 @@ pub trait Output<E: Engine> {
|
||||||
//impl<E: Engine> Render<E> for &dyn Render<E> {}
|
//impl<E: Engine> Render<E> for &dyn Render<E> {}
|
||||||
//impl<E: Engine> Render<E> for &mut dyn Render<E> {}
|
//impl<E: Engine> Render<E> for &mut dyn Render<E> {}
|
||||||
//impl<E: Engine> Render<E> for Box<dyn Render<E>> {}
|
//impl<E: Engine> Render<E> for Box<dyn Render<E>> {}
|
||||||
//impl<E: Engine, R: Render<E>> Render<E> for &R {}
|
impl<E: Engine, R: Render<E>> Render<E> for &R {}
|
||||||
//impl<E: Engine, R: Render<E>> Render<E> for &mut R {}
|
//impl<E: Engine, R: Render<E>> Render<E> for &mut R {}
|
||||||
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {}
|
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {}
|
||||||
//impl<E: Engine, R: Render<E>> Render<E> for Arc<R> {}
|
//impl<E: Engine, R: Render<E>> Render<E> for Arc<R> {}
|
||||||
//impl<E: Engine, R: Render<E>> Render<E> for Mutex<R> {}
|
//impl<E: Engine, R: Render<E>> Render<E> for Mutex<R> {}
|
||||||
//impl<E: Engine, R: Render<E>> Render<E> for RwLock<R> {}
|
//impl<E: Engine, R: Render<E>> Render<E> for RwLock<R> {}
|
||||||
|
|
@ -101,38 +133,6 @@ impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
/// Define custom content for a struct.
|
|
||||||
#[macro_export] macro_rules! render {
|
|
||||||
|
|
||||||
// Implement for all engines
|
|
||||||
(|$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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implement for a specific 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<E: Engine, R: Render<E>> Render<E> for &R {
|
impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
(*self).min_size(to)
|
(*self).min_size(to)
|
||||||
|
|
|
||||||
|
|
@ -25,18 +25,6 @@ pub(crate) use ratatui::{
|
||||||
|
|
||||||
impl Coordinate for u16 {}
|
impl Coordinate for u16 {}
|
||||||
|
|
||||||
impl Size<u16> for [u16;2] {
|
|
||||||
fn x (&self) -> u16 { self[0] }
|
|
||||||
fn y (&self) -> u16 { self[1] }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Area<u16> for [u16;4] {
|
|
||||||
fn x (&self) -> u16 { self[0] }
|
|
||||||
fn y (&self) -> u16 { self[1] }
|
|
||||||
fn w (&self) -> u16 { self[2] }
|
|
||||||
fn h (&self) -> u16 { self[3] }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Tui {
|
pub struct Tui {
|
||||||
pub exited: Arc<AtomicBool>,
|
pub exited: Arc<AtomicBool>,
|
||||||
pub buffer: Buffer,
|
pub buffer: Buffer,
|
||||||
|
|
@ -349,19 +337,7 @@ pub fn half_block (lower: bool, upper: bool) -> Option<char> {
|
||||||
|
|
||||||
//impl<T: Content<Tui>> Render<Tui> for T {}
|
//impl<T: Content<Tui>> Render<Tui> for T {}
|
||||||
|
|
||||||
impl Render<Tui> for &str {
|
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Render<Tui> for &String {
|
|
||||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||||
// TODO: line breaks
|
// TODO: line breaks
|
||||||
Ok(Some([self.chars().count() as u16, 1]))
|
Ok(Some([self.chars().count() as u16, 1]))
|
||||||
|
|
|
||||||
673
layout/Cargo.lock
generated
Normal file
673
layout/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,673 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.24.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.74"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "better-panic"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fa9e1d11a268684cbd90ed36370d7577afb6c62d912ddff5c15fc34343e5036"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"console",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cassowary"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "castaway"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
|
||||||
|
dependencies = [
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "compact_str"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
|
||||||
|
dependencies = [
|
||||||
|
"castaway",
|
||||||
|
"cfg-if",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console"
|
||||||
|
version = "0.15.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
|
||||||
|
dependencies = [
|
||||||
|
"encode_unicode",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"crossterm_winapi",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"signal-hook",
|
||||||
|
"signal-hook-mio",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm_winapi"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.31.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||||
|
dependencies = [
|
||||||
|
"allocator-api2",
|
||||||
|
"equivalent",
|
||||||
|
"foldhash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.169"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lru"
|
||||||
|
version = "0.12.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.36.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ratatui"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cassowary",
|
||||||
|
"compact_str",
|
||||||
|
"crossterm",
|
||||||
|
"itertools 0.12.1",
|
||||||
|
"lru",
|
||||||
|
"paste",
|
||||||
|
"stability",
|
||||||
|
"strum",
|
||||||
|
"unicode-segmentation",
|
||||||
|
"unicode-truncate",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-mio"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"signal-hook",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
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 = "strum"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tek_engine"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"better-panic",
|
||||||
|
"crossterm",
|
||||||
|
"ratatui",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tek_layout"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"tek_engine",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-truncate"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
||||||
|
dependencies = [
|
||||||
|
"itertools 0.13.0",
|
||||||
|
"unicode-segmentation",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
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",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
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_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",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
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"
|
||||||
7
layout/Cargo.toml
Normal file
7
layout/Cargo.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "tek_layout"
|
||||||
|
edition = "2021"
|
||||||
|
version = "0.2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tek_engine = { path = "../engine" }
|
||||||
139
layout/src/collection.rs
Normal file
139
layout/src/collection.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
mod bsp; pub use self::bsp::*;
|
||||||
|
mod layers; pub use self::layers::*;
|
||||||
|
mod split; pub use self::split::*;
|
||||||
|
mod stack; pub use self::stack::*;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// A function or closure that emits renderables.
|
||||||
|
pub trait CollectCallback<E: Engine>: Send
|
||||||
|
+ Sync
|
||||||
|
+ Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// Any function or closure that emits renderables for the given engine matches [CollectCallback].
|
||||||
|
impl<E, F> CollectCallback<E> for F
|
||||||
|
where
|
||||||
|
E: Engine,
|
||||||
|
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||||
|
{}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub enum Collect<'a, E: Engine, const N: usize> {
|
||||||
|
Callback(CallbackCollection<'a, E>),
|
||||||
|
//Iterator(IteratorCollection<'a, E>),
|
||||||
|
Array(ArrayCollection<'a, E, N>),
|
||||||
|
Slice(SliceCollection<'a, E>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine, const N: usize> Collect<'a, E, N> {
|
||||||
|
pub fn iter (&'a self) -> CollectIterator<'a, E, N> {
|
||||||
|
CollectIterator(0, &self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine, const N: usize> From<CallbackCollection<'a, E>> for Collect<'a, E, N> {
|
||||||
|
fn from (callback: CallbackCollection<'a, E>) -> Self {
|
||||||
|
Self::Callback(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine, const N: usize> From<SliceCollection<'a, E>> for Collect<'a, E, N> {
|
||||||
|
fn from (slice: SliceCollection<'a, E>) -> Self {
|
||||||
|
Self::Slice(slice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine, const N: usize> From<ArrayCollection<'a, E, N>> for Collect<'a, E, N>{
|
||||||
|
fn from (array: ArrayCollection<'a, E, N>) -> Self {
|
||||||
|
Self::Array(array)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CallbackCollection<'a, E> =
|
||||||
|
&'a dyn Fn(&'a mut dyn FnMut(&dyn Render<E>)->Usually<()>);
|
||||||
|
|
||||||
|
//type IteratorCollection<'a, E> =
|
||||||
|
//&'a mut dyn Iterator<Item = dyn Render<E>>;
|
||||||
|
|
||||||
|
type SliceCollection<'a, E> =
|
||||||
|
&'a [&'a dyn Render<E>];
|
||||||
|
|
||||||
|
type ArrayCollection<'a, E, const N: usize> =
|
||||||
|
[&'a dyn Render<E>; N];
|
||||||
|
|
||||||
|
pub struct CollectIterator<'a, E: Engine, const N: usize>(usize, &'a Collect<'a, E, N>);
|
||||||
|
|
||||||
|
impl<'a, E: Engine, const N: usize> Iterator for CollectIterator<'a, E, N> {
|
||||||
|
type Item = &'a dyn Render<E>;
|
||||||
|
fn next (&mut self) -> Option<Self::Item> {
|
||||||
|
match self.1 {
|
||||||
|
Collect::Callback(callback) => {
|
||||||
|
todo!()
|
||||||
|
},
|
||||||
|
//Collection::Iterator(iterator) => {
|
||||||
|
//iterator.next()
|
||||||
|
//},
|
||||||
|
Collect::Array(array) => {
|
||||||
|
if let Some(item) = array.get(self.0) {
|
||||||
|
self.0 += 1;
|
||||||
|
//Some(item)
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collect::Slice(slice) => {
|
||||||
|
if let Some(item) = slice.get(self.0) {
|
||||||
|
self.0 += 1;
|
||||||
|
//Some(item)
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub struct Map<E: Engine, T, I: Iterator<Item=T>, R: Render<E>, F: Fn(T)->R>(
|
||||||
|
PhantomData<E>,
|
||||||
|
I,
|
||||||
|
F
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub struct Reduce<E: Engine, T, I: Iterator<Item=T>, R: Render<E>, F: Fn(&dyn Render<E>, T)->R>(
|
||||||
|
PhantomData<(E, R)>,
|
||||||
|
I,
|
||||||
|
F
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<E: Engine, T, I: Iterator<Item=T>+Send+Sync, R: Render<E>, F: Fn(&dyn Render<E>, T)->R+Send+Sync> Render<E> for Reduce<E, T, I, R, F> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(test)] #[test] fn test_bsp () {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
99
layout/src/collection/bsp.rs
Normal file
99
layout/src/collection/bsp.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub enum Bsp<E: Engine, X: Render<E>, Y: Render<E>> {
|
||||||
|
/// X is north of Y
|
||||||
|
N(Option<X>, Option<Y>),
|
||||||
|
/// X is south of Y
|
||||||
|
S(Option<X>, Option<Y>),
|
||||||
|
/// X is east of Y
|
||||||
|
E(Option<X>, Option<Y>),
|
||||||
|
/// X is west of Y
|
||||||
|
W(Option<X>, Option<Y>),
|
||||||
|
/// X is above Y
|
||||||
|
A(Option<X>, Option<Y>),
|
||||||
|
/// X is below Y
|
||||||
|
B(Option<X>, Option<Y>),
|
||||||
|
/// Should be avoided.
|
||||||
|
Null(PhantomData<E>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, X: Render<E>, Y: Render<E>> Bsp<E, X, Y> {
|
||||||
|
pub fn new (x: X) -> Self { Self::A(Some(x), None) }
|
||||||
|
pub fn n (x: X, y: Y) -> Self { Self::N(Some(x), Some(y)) }
|
||||||
|
pub fn s (x: X, y: Y) -> Self { Self::S(Some(x), Some(y)) }
|
||||||
|
pub fn e (x: X, y: Y) -> Self { Self::E(Some(x), Some(y)) }
|
||||||
|
pub fn w (x: X, y: Y) -> Self { Self::W(Some(x), Some(y)) }
|
||||||
|
pub fn a (x: X, y: Y) -> Self { Self::A(Some(x), Some(y)) }
|
||||||
|
pub fn b (x: X, y: Y) -> Self { Self::B(Some(x), Some(y)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, X: Render<E>, Y: Render<E>> Default for Bsp<E, X, Y> {
|
||||||
|
fn default () -> Self {
|
||||||
|
Self::Null(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, X: Render<E>, Y: Render<E>> Render<E> for Bsp<E, X, Y> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
Ok(Some(match self {
|
||||||
|
Self::Null(_) => [0.into(), 0.into()].into(),
|
||||||
|
Self::S(a, b) => {
|
||||||
|
let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
[a.w().max(b.w()), a.h() + b.h()].into()
|
||||||
|
},
|
||||||
|
Self::E(a, b) => {
|
||||||
|
let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
[a.w() + b.w(), a.h().max(b.h())].into()
|
||||||
|
},
|
||||||
|
Self::W(a, b) => {
|
||||||
|
let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
[a.w() + b.w(), a.h().max(b.h())].into()
|
||||||
|
},
|
||||||
|
Self::N(a, b) => {
|
||||||
|
let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into());
|
||||||
|
[a.w().max(b.w()), a.h() + b.h()].into()
|
||||||
|
},
|
||||||
|
_ => todo!()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
let n = [0.into(), 0.into()].into();
|
||||||
|
let s = to.area().wh().into();
|
||||||
|
Ok(match self {
|
||||||
|
Self::Null(_) => {},
|
||||||
|
Self::S(a, b) => {
|
||||||
|
let s_a = a.min_size(s)?.unwrap_or(n);
|
||||||
|
let _ = b.min_size(s)?.unwrap_or(n);
|
||||||
|
let h = s_a.h().into();
|
||||||
|
to.render_in(to.area().clip_h(h).into(), a)?;
|
||||||
|
to.render_in(to.area().shrink_y(h).push_y(h).into(), b)?;
|
||||||
|
},
|
||||||
|
Self::E(a, b) => {
|
||||||
|
let s_a = a.min_size(s)?.unwrap_or(n);
|
||||||
|
let _ = b.min_size(s)?.unwrap_or(n);
|
||||||
|
let w = s_a.w().into();
|
||||||
|
to.render_in(to.area().clip_w(w).into(), a)?;
|
||||||
|
to.render_in(to.area().push_x(w).shrink_x(w).into(), b)?;
|
||||||
|
},
|
||||||
|
Self::W(a, b) => {
|
||||||
|
let s_a = a.min_size(s)?.unwrap_or(n);
|
||||||
|
let _ = b.min_size(s)?.unwrap_or(n);
|
||||||
|
let w = (to.area().w() - s_a.w()).into();
|
||||||
|
to.render_in(to.area().push_x(w).into(), a)?;
|
||||||
|
to.render_in(to.area().shrink_x(w).into(), b)?;
|
||||||
|
},
|
||||||
|
Self::N(a, b) => {
|
||||||
|
let s_a = a.min_size(s)?.unwrap_or(n);
|
||||||
|
let _ = b.min_size(s)?.unwrap_or(n);
|
||||||
|
let h = to.area().h() - s_a.h();
|
||||||
|
to.render_in(to.area().push_y(h).into(), a)?;
|
||||||
|
to.render_in(to.area().shrink_y(h).into(), b)?;
|
||||||
|
},
|
||||||
|
_ => todo!()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
56
layout/src/collection/layers.rs
Normal file
56
layout/src/collection/layers.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// Renders multiple things on top of each other,
|
||||||
|
/// in the order they are provided by the callback.
|
||||||
|
/// Total size is largest width x largest height.
|
||||||
|
pub struct Layers<E: Engine, F: CollectCallback<E>>(pub F, PhantomData<E>);
|
||||||
|
|
||||||
|
/// Shorthand for defining an instance of [Layers].
|
||||||
|
#[macro_export] macro_rules! lay {
|
||||||
|
([$($expr:expr),* $(,)?]) => {
|
||||||
|
Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
(![$($expr:expr),* $(,)?]) => {
|
||||||
|
Layers::new(|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
($expr:expr) => {
|
||||||
|
Layers::new($expr)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
E: Engine,
|
||||||
|
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||||
|
> Layers<E, F> {
|
||||||
|
#[inline]
|
||||||
|
pub fn new (build: F) -> Self {
|
||||||
|
Self(build, Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, F> Render<E> for Layers<E, F>
|
||||||
|
where
|
||||||
|
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||||
|
{
|
||||||
|
fn min_size (&self, area: E::Size) -> Perhaps<E::Size> {
|
||||||
|
let mut w: E::Unit = 0.into();
|
||||||
|
let mut h: E::Unit = 0.into();
|
||||||
|
(self.0)(&mut |layer| {
|
||||||
|
if let Some(layer_area) = layer.min_size(area)? {
|
||||||
|
w = w.max(layer_area.w());
|
||||||
|
h = h.max(layer_area.h());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(Some([w, h].into()))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
if let Some(size) = self.min_size(to.area().wh().into())? {
|
||||||
|
(self.0)(&mut |layer|to.render_in(to.area().clip(size).into(), layer))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
169
layout/src/collection/split.rs
Normal file
169
layout/src/collection/split.rs
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// A binary split with fixed proportion
|
||||||
|
pub struct Split<E, A, B>(pub bool, pub Direction, pub E::Unit, A, B, PhantomData<E>)
|
||||||
|
where E: Engine, A: Render<E>, B: Render<E>;
|
||||||
|
|
||||||
|
impl<E: Engine, A: Render<E>, B: Render<E>> Split<E, A, B> {
|
||||||
|
#[inline] pub fn new (flip: bool, direction: Direction, proportion: E::Unit, a: A, b: B) -> Self {
|
||||||
|
Self(flip, direction, proportion, a, b, Default::default())
|
||||||
|
}
|
||||||
|
#[inline] pub fn n (flip: bool, proportion: E::Unit, a: A, b: B) -> Self {
|
||||||
|
Self::new(flip, North, proportion, a, b)
|
||||||
|
}
|
||||||
|
#[inline] pub fn s (flip: bool, proportion: E::Unit, a: A, b: B) -> Self {
|
||||||
|
Self::new(flip, South, proportion, a, b)
|
||||||
|
}
|
||||||
|
#[inline] pub fn e (flip: bool, proportion: E::Unit, a: A, b: B) -> Self {
|
||||||
|
Self::new(flip, West, proportion, a, b)
|
||||||
|
}
|
||||||
|
#[inline] pub fn w (flip: bool, proportion: E::Unit, a: A, b: B) -> Self {
|
||||||
|
Self::new(flip, East, proportion, a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Split<E, A, B> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
Ok(Some(to))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
let (a, b) = self.1.split_fixed(self.2, self.3);
|
||||||
|
Ok(if self.0 {
|
||||||
|
to.render_in(a.into(), &self.4)?;
|
||||||
|
to.render_in(b.into(), &self.3)?;
|
||||||
|
} else {
|
||||||
|
to.render_in(a.into(), &self.3)?;
|
||||||
|
to.render_in(b.into(), &self.4)?;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, F> Render<E> for Stack<E, F>
|
||||||
|
where
|
||||||
|
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||||
|
{
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
match self.1 {
|
||||||
|
|
||||||
|
South => {
|
||||||
|
let mut w: E::Unit = 0.into();
|
||||||
|
let mut h: E::Unit = 0.into();
|
||||||
|
(self.0)(&mut |component: &dyn Render<E>| {
|
||||||
|
let max = to.h().minus(h);
|
||||||
|
if max > E::Unit::zero() {
|
||||||
|
let item = Max::y(max, Push::y(h, component));
|
||||||
|
let size = item.min_size(to)?.map(|size|size.wh());
|
||||||
|
if let Some([width, height]) = size {
|
||||||
|
h = h + height.into();
|
||||||
|
w = w.max(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(Some([w, h].into()))
|
||||||
|
},
|
||||||
|
|
||||||
|
East => {
|
||||||
|
let mut w: E::Unit = 0.into();
|
||||||
|
let mut h: E::Unit = 0.into();
|
||||||
|
(self.0)(&mut |component: &dyn Render<E>| {
|
||||||
|
let max = to.w().minus(w);
|
||||||
|
if max > E::Unit::zero() {
|
||||||
|
let item = Max::x(max, Push::x(h, component));
|
||||||
|
let size = item.min_size(to)?.map(|size|size.wh());
|
||||||
|
if let Some([width, height]) = size {
|
||||||
|
w = w + width.into();
|
||||||
|
h = h.max(height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(Some([w, h].into()))
|
||||||
|
},
|
||||||
|
|
||||||
|
North => {
|
||||||
|
let mut w: E::Unit = 0.into();
|
||||||
|
let mut h: E::Unit = 0.into();
|
||||||
|
(self.0)(&mut |component: &dyn Render<E>| {
|
||||||
|
let max = to.h().minus(h);
|
||||||
|
if max > E::Unit::zero() {
|
||||||
|
let item = Max::y(to.h() - h, component);
|
||||||
|
let size = item.min_size(to)?.map(|size|size.wh());
|
||||||
|
if let Some([width, height]) = size {
|
||||||
|
h = h + height.into();
|
||||||
|
w = w.max(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(Some([w, h].into()))
|
||||||
|
},
|
||||||
|
|
||||||
|
West => {
|
||||||
|
let w: E::Unit = 0.into();
|
||||||
|
let h: E::Unit = 0.into();
|
||||||
|
(self.0)(&mut |component: &dyn Render<E>| {
|
||||||
|
if w < to.w() {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(Some([w, h].into()))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
let area = to.area();
|
||||||
|
let mut w = 0.into();
|
||||||
|
let mut h = 0.into();
|
||||||
|
match self.1 {
|
||||||
|
South => {
|
||||||
|
(self.0)(&mut |item| {
|
||||||
|
if h < area.h() {
|
||||||
|
let item = Max::y(area.h() - h, Push::y(h, item));
|
||||||
|
let show = item.min_size(area.wh().into())?.map(|s|s.wh());
|
||||||
|
if let Some([width, height]) = show {
|
||||||
|
item.render(to)?;
|
||||||
|
h = h + height;
|
||||||
|
if width > w { w = width }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
},
|
||||||
|
East => {
|
||||||
|
(self.0)(&mut |item| {
|
||||||
|
if w < area.w() {
|
||||||
|
let item = Max::x(area.w() - w, Push::x(w, item));
|
||||||
|
let show = item.min_size(area.wh().into())?.map(|s|s.wh());
|
||||||
|
if let Some([width, height]) = show {
|
||||||
|
item.render(to)?;
|
||||||
|
w = width + w;
|
||||||
|
if height > h { h = height }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
},
|
||||||
|
North => {
|
||||||
|
(self.0)(&mut |item| {
|
||||||
|
if h < area.h() {
|
||||||
|
let show = item.min_size([area.w(), area.h().minus(h)].into())?.map(|s|s.wh());
|
||||||
|
if let Some([width, height]) = show {
|
||||||
|
Shrink::y(height, Push::y(area.h() - height, item))
|
||||||
|
.render(to)?;
|
||||||
|
h = h + height;
|
||||||
|
if width > w { w = width }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
},
|
||||||
|
_ => todo!()
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
65
layout/src/collection/stack.rs
Normal file
65
layout/src/collection/stack.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub struct Stack<E: Engine, F: CollectCallback<E>>(pub F, pub Direction, PhantomData<E>);
|
||||||
|
|
||||||
|
impl<E: Engine, F: CollectCallback<E>> Stack<E, F> {
|
||||||
|
#[inline] pub fn new (direction: Direction, build: F) -> Self {
|
||||||
|
Self(build, direction, Default::default())
|
||||||
|
}
|
||||||
|
#[inline] pub fn right (build: F) -> Self {
|
||||||
|
Self::new(East, build)
|
||||||
|
}
|
||||||
|
#[inline] pub fn down (build: F) -> Self {
|
||||||
|
Self::new(South, build)
|
||||||
|
}
|
||||||
|
#[inline] pub fn up (build: F) -> Self {
|
||||||
|
Self::new(North, build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! col {
|
||||||
|
([$($expr:expr),* $(,)?]) => {
|
||||||
|
Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
(![$($expr:expr),* $(,)?]) => {
|
||||||
|
Stack::down(|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
($expr:expr) => {
|
||||||
|
Stack::down($expr)
|
||||||
|
};
|
||||||
|
($pat:pat in $collection:expr => $item:expr) => {
|
||||||
|
Stack::down(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! col_up {
|
||||||
|
([$($expr:expr),* $(,)?]) => {
|
||||||
|
Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
(![$($expr:expr),* $(,)?]) => {
|
||||||
|
Stack::up(|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
($expr:expr) => {
|
||||||
|
Stack::up(expr)
|
||||||
|
};
|
||||||
|
($pat:pat in $collection:expr => $item:expr) => {
|
||||||
|
Stack::up(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! row {
|
||||||
|
([$($expr:expr),* $(,)?]) => {
|
||||||
|
Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
(![$($expr:expr),* $(,)?]) => {
|
||||||
|
Stack::right(|add|{ $(add(&$expr)?;)* Ok(()) })
|
||||||
|
};
|
||||||
|
($expr:expr) => {
|
||||||
|
Stack::right($expr)
|
||||||
|
};
|
||||||
|
($pat:pat in $collection:expr => $item:expr) => {
|
||||||
|
Stack::right(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
30
layout/src/direction.rs
Normal file
30
layout/src/direction.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// A cardinal direction.
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
pub enum Direction { North, South, West, East, }
|
||||||
|
pub use self::Direction::*;
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
#[inline]
|
||||||
|
pub fn split_fixed <N: Coordinate> (self, area: impl Area<N>, a: N) -> ([N;4],[N;4]) {
|
||||||
|
match self {
|
||||||
|
North => (
|
||||||
|
[area.x(), (area.y()+area.h()).minus(a), area.w(), a],
|
||||||
|
[area.x(), area.y(), area.w(), area.h().minus(a)],
|
||||||
|
),
|
||||||
|
South => (
|
||||||
|
[area.x(), area.y(), area.w(), a],
|
||||||
|
[area.x(), area.y() + a, area.w(), area.h().minus(a)],
|
||||||
|
),
|
||||||
|
East => (
|
||||||
|
[area.x(), area.y(), a, area.h()],
|
||||||
|
[area.x() + a, area.y(), area.w().minus(a), area.h()],
|
||||||
|
),
|
||||||
|
West => (
|
||||||
|
[area.x() + area.w() - a, area.y(), a, area.h()],
|
||||||
|
[area.x(), area.y(), area.w() - a, area.h()],
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
layout/src/layers.rs
Normal file
1
layout/src/layers.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use crate::*;
|
||||||
18
layout/src/lib.rs
Normal file
18
layout/src/lib.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
pub use ::tek_engine;
|
||||||
|
pub(crate) use ::tek_engine::*;
|
||||||
|
|
||||||
|
pub(crate) use std::ops::{Add, Sub, Mul, Div};
|
||||||
|
pub(crate) use std::fmt::{Display, Debug};
|
||||||
|
pub(crate) use std::marker::PhantomData;
|
||||||
|
pub(crate) use std::sync::atomic::Ordering::*;
|
||||||
|
|
||||||
|
mod collection; pub use self::collection::*;
|
||||||
|
mod direction; pub use self::direction::*;
|
||||||
|
mod layers; pub use self::layers::*;
|
||||||
|
mod logic; pub use self::logic::*;
|
||||||
|
mod space; pub use self::space::*;
|
||||||
|
mod transform; pub use self::transform::*;
|
||||||
|
|
||||||
|
#[cfg(test)] #[test] fn test_layout () -> Usually<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
43
layout/src/logic.rs
Normal file
43
layout/src/logic.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// 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>);
|
||||||
|
|
||||||
|
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(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
317
layout/src/space.rs
Normal file
317
layout/src/space.rs
Normal file
|
|
@ -0,0 +1,317 @@
|
||||||
|
use crate::*;
|
||||||
|
use std::sync::{Arc, atomic::AtomicUsize};
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
pub fn is_north (&self) -> bool { matches!(self, Self::North) }
|
||||||
|
pub fn is_south (&self) -> bool { matches!(self, Self::South) }
|
||||||
|
pub fn is_east (&self) -> bool { matches!(self, Self::West) }
|
||||||
|
pub fn is_west (&self) -> bool { matches!(self, Self::East) }
|
||||||
|
/// Return next direction clockwise
|
||||||
|
pub fn cw (&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::North => Self::East,
|
||||||
|
Self::South => Self::West,
|
||||||
|
Self::West => Self::North,
|
||||||
|
Self::East => Self::South,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Return next direction counterclockwise
|
||||||
|
pub fn ccw (&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::North => Self::West,
|
||||||
|
Self::South => Self::East,
|
||||||
|
Self::West => Self::South,
|
||||||
|
Self::East => Self::North,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait AreaMod<N: Coordinate>: Area<N> {
|
||||||
|
fn x2 (&self) -> N {
|
||||||
|
self.x() + self.w()
|
||||||
|
}
|
||||||
|
fn y2 (&self) -> N {
|
||||||
|
self.y() + self.h()
|
||||||
|
}
|
||||||
|
#[inline] fn xywh (&self) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w(), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn lrtb (&self) -> [N;4] {
|
||||||
|
[self.x(), self.x2(), self.y(), self.y2()]
|
||||||
|
}
|
||||||
|
#[inline] fn push_x (&self, x: N) -> [N;4] {
|
||||||
|
[self.x() + x, self.y(), self.w(), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn push_y (&self, y: N) -> [N;4] {
|
||||||
|
[self.x(), self.y() + y, self.w(), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn shrink_x (&self, x: N) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w().minus(x), self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn shrink_y (&self, y: N) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w(), self.h().minus(y)]
|
||||||
|
}
|
||||||
|
#[inline] fn set_w (&self, w: N) -> [N;4] {
|
||||||
|
[self.x(), self.y(), w, self.h()]
|
||||||
|
}
|
||||||
|
#[inline] fn set_h (&self, h: N) -> [N;4] {
|
||||||
|
[self.x(), self.y(), self.w(), h]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Coordinate, A: Area<N>> AreaMod<N> for A {}
|
||||||
|
|
||||||
|
pub trait HasSize<E: Engine> {
|
||||||
|
fn size (&self) -> &Measure<E>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! has_size {
|
||||||
|
(<$E:ty>|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => {
|
||||||
|
impl $(<$($L),*$($T $(: $U)?),*>)? HasSize<$E> for $Struct $(<$($L),*$($T),*>)? {
|
||||||
|
fn size (&$self) -> &Measure<$E> { $cb }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A widget that tracks its render width and height
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Measure<E: Engine> {
|
||||||
|
_engine: PhantomData<E>,
|
||||||
|
pub x: Arc<AtomicUsize>,
|
||||||
|
pub y: Arc<AtomicUsize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Shrink<E, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Grow<E, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Shrink<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
Ok(self.inner().min_size(to)?.map(|to|match *self {
|
||||||
|
Self::X(w, _) => [
|
||||||
|
if to.w() > w { to.w() - w } else { 0.into() },
|
||||||
|
to.h()
|
||||||
|
],
|
||||||
|
Self::Y(h, _) => [
|
||||||
|
to.w(),
|
||||||
|
if to.h() > h { to.h() - h } else { 0.into() }
|
||||||
|
],
|
||||||
|
Self::XY(w, h, _) => [
|
||||||
|
if to.w() > w { to.w() - w } else { 0.into() },
|
||||||
|
if to.h() > h { to.h() - h } else { 0.into() }
|
||||||
|
],
|
||||||
|
}.into()))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
Ok(self.min_size(to.area().wh().into())?
|
||||||
|
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||||
|
.transpose()?.unwrap_or(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Grow<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
Ok(self.inner().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()))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
Ok(self.min_size(to.area().wh().into())?
|
||||||
|
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||||
|
.transpose()?.unwrap_or(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, W: Render<E>> Fill<E, W> {
|
||||||
|
fn inner (&self) -> &W {
|
||||||
|
match self {
|
||||||
|
Self::X(inner) => &inner,
|
||||||
|
Self::Y(inner) => &inner,
|
||||||
|
Self::XY(inner) => &inner,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn w (fill: W) -> Self {
|
||||||
|
Self::X(fill)
|
||||||
|
}
|
||||||
|
pub fn h (fill: W) -> Self {
|
||||||
|
Self::Y(fill)
|
||||||
|
}
|
||||||
|
pub fn wh (fill: W) -> Self {
|
||||||
|
Self::XY(fill)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, W: Render<E>> Render<E> for Fill<E, W> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
let area = self.inner().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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
self.inner().render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Fixed<E, T> {
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn w (x: E::Unit, w: T) -> Self {
|
||||||
|
Self::X(x, w)
|
||||||
|
}
|
||||||
|
pub fn h (y: E::Unit, w: T) -> Self {
|
||||||
|
Self::Y(y, w)
|
||||||
|
}
|
||||||
|
pub fn wh (x: E::Unit, y: E::Unit, w: T) -> Self {
|
||||||
|
Self::XY(x, y, w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Fixed<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
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 },
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
// 🡘 🡙 ←🡙→
|
||||||
|
if let Some(size) = self.min_size(to.area().wh().into())? {
|
||||||
|
to.render_in(to.area().clip(size).into(), self.inner())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Min<E, T> {
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Min<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
Ok(self.inner().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()))
|
||||||
|
}
|
||||||
|
// TODO: 🡘 🡙 ←🡙→
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
Ok(self.min_size(to.area().wh().into())?
|
||||||
|
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||||
|
.transpose()?.unwrap_or(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Max<E, T> {
|
||||||
|
fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Max<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
Ok(self.inner().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()))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
Ok(self.min_size(to.area().wh().into())?
|
||||||
|
.map(|size|to.render_in(to.area().clip(size).into(), self.inner()))
|
||||||
|
.transpose()?.unwrap_or(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> Clone for Measure<E> {
|
||||||
|
fn clone (&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_engine: Default::default(),
|
||||||
|
x: self.x.clone(),
|
||||||
|
y: self.y.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> std::fmt::Debug for Measure<E> {
|
||||||
|
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
|
f.debug_struct("Measure")
|
||||||
|
.field("width", &self.x)
|
||||||
|
.field("height", &self.y)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> Measure<E> {
|
||||||
|
pub fn w (&self) -> usize { self.x.load(Relaxed) }
|
||||||
|
pub fn h (&self) -> usize { self.y.load(Relaxed) }
|
||||||
|
pub fn wh (&self) -> [usize;2] { [self.w(), self.h()] }
|
||||||
|
pub fn set_w (&self, w: impl Into<usize>) { self.x.store(w.into(), Relaxed) }
|
||||||
|
pub fn set_h (&self, h: impl Into<usize>) { self.y.store(h.into(), Relaxed) }
|
||||||
|
pub fn set_wh (&self, w: impl Into<usize>, h: impl Into<usize>) { self.set_w(w); self.set_h(h); }
|
||||||
|
pub fn format (&self) -> String { format!("{}x{}", self.w(), self.h()) }
|
||||||
|
pub fn new () -> Self {
|
||||||
|
Self {
|
||||||
|
_engine: PhantomData::default(),
|
||||||
|
x: Arc::new(0.into()),
|
||||||
|
y: Arc::new(0.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pub trait LayoutDebug<E: Engine> {
|
||||||
|
//fn debug <W: Render<E>> (other: W) -> DebugOverlay<E, W> {
|
||||||
|
//DebugOverlay(Default::default(), other)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//impl<E: Engine> LayoutDebug<E> for E {}
|
||||||
372
layout/src/transform.rs
Normal file
372
layout/src/transform.rs
Normal file
|
|
@ -0,0 +1,372 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
macro_rules! by_axis {
|
||||||
|
(!$Enum:ident) => {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(+$Enum:ident) => {
|
||||||
|
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||||
|
pub fn x (x: E::Unit, item: T) -> Self {
|
||||||
|
Self::X(x, item)
|
||||||
|
}
|
||||||
|
pub fn y (y: E::Unit, item: T) -> Self {
|
||||||
|
Self::Y(y, item)
|
||||||
|
}
|
||||||
|
pub fn xy (x: E::Unit, y: E::Unit, item: T) -> Self {
|
||||||
|
Self::XY(x, y, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shrink drawing area
|
||||||
|
pub enum Shrink<E: Engine, T: Render<E>> {
|
||||||
|
/// Decrease width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Decrease height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Decrease width and height
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Shrink);
|
||||||
|
|
||||||
|
/// Expand drawing area
|
||||||
|
pub enum Grow<E: Engine, T: Render<E>> {
|
||||||
|
/// Increase width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Increase height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Increase width and height
|
||||||
|
XY(E::Unit, E::Unit, T)
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Grow);
|
||||||
|
|
||||||
|
pub enum Fill<E: Engine, W: Render<E>> {
|
||||||
|
_Unused(PhantomData<E>),
|
||||||
|
/// Maximize width
|
||||||
|
X(W),
|
||||||
|
/// Maximize height
|
||||||
|
Y(W),
|
||||||
|
/// Maximize width and height
|
||||||
|
XY(W),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(!Fill);
|
||||||
|
|
||||||
|
/// Enforce fixed size of drawing area
|
||||||
|
pub enum Fixed<E: Engine, T: Render<E>> {
|
||||||
|
/// Set width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Set height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Set width and height
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Fixed);
|
||||||
|
|
||||||
|
/// Enforce minimum size of drawing area
|
||||||
|
pub enum Min<E: Engine, T: Render<E>> {
|
||||||
|
/// Enforce minimum width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Enforce minimum height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Enforce minimum width and height
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Min);
|
||||||
|
|
||||||
|
/// Enforce maximum size of drawing area
|
||||||
|
pub enum Max<E: Engine, T: Render<E>> {
|
||||||
|
/// Enforce maximum width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Enforce maximum height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Enforce maximum width and height
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Max);
|
||||||
|
|
||||||
|
/// Increment origin point of drawing area
|
||||||
|
pub enum Push<E: Engine, T: Render<E>> {
|
||||||
|
/// Move origin to the right
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Move origin downwards
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Move origin to the right and downwards
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Push);
|
||||||
|
|
||||||
|
/// Decrement origin point of drawing area
|
||||||
|
pub enum Pull<E: Engine, T: Render<E>> {
|
||||||
|
/// Move origin to the right
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Move origin downwards
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Move origin to the right and downwards
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Pull);
|
||||||
|
|
||||||
|
/// Shrink from each side
|
||||||
|
pub enum Padding<E: Engine, T> {
|
||||||
|
/// Decrease width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Decrease height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Decrease width and height
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Padding);
|
||||||
|
|
||||||
|
/// Grow on each side
|
||||||
|
pub enum Margin<E: Engine, T: Render<E>> {
|
||||||
|
/// Increase width
|
||||||
|
X(E::Unit, T),
|
||||||
|
/// Increase height
|
||||||
|
Y(E::Unit, T),
|
||||||
|
/// Increase width and height
|
||||||
|
XY(E::Unit, E::Unit, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
by_axis!(+Margin);
|
||||||
|
|
||||||
|
/// A scrollable area.
|
||||||
|
pub struct Scroll<E, F>(pub F, pub Direction, pub u64, PhantomData<E>)
|
||||||
|
where
|
||||||
|
E: Engine,
|
||||||
|
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>;
|
||||||
|
|
||||||
|
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||||
|
pub enum Align<E: Engine, T: Render<E>> {
|
||||||
|
_Unused(PhantomData<E>),
|
||||||
|
/// Draw at center of container
|
||||||
|
Center(T),
|
||||||
|
/// Draw at center of X axis
|
||||||
|
X(T),
|
||||||
|
/// Draw at center of Y axis
|
||||||
|
Y(T),
|
||||||
|
/// Draw at upper left corner of contaier
|
||||||
|
NW(T),
|
||||||
|
/// Draw at center of upper edge of container
|
||||||
|
N(T),
|
||||||
|
/// Draw at right left corner of contaier
|
||||||
|
NE(T),
|
||||||
|
/// Draw at center of left edge of container
|
||||||
|
W(T),
|
||||||
|
/// Draw at center of right edge of container
|
||||||
|
E(T),
|
||||||
|
/// Draw at lower left corner of container
|
||||||
|
SW(T),
|
||||||
|
/// Draw at center of lower edge of container
|
||||||
|
S(T),
|
||||||
|
/// Draw at lower right edge of container
|
||||||
|
SE(T)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Push<E, T> {
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
use Push::*;
|
||||||
|
match self { X(_, i) => i, Y(_, i) => i, XY(_, _, i) => i, }
|
||||||
|
}
|
||||||
|
pub fn dx (&self) -> E::Unit {
|
||||||
|
use Push::*;
|
||||||
|
match self { X(x, _) => *x, Y(_, _) => E::Unit::default(), XY(x, _, _) => *x, }
|
||||||
|
}
|
||||||
|
pub fn dy (&self) -> E::Unit {
|
||||||
|
use Push::*;
|
||||||
|
match self { X(_, _) => E::Unit::default(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Push<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
self.inner().min_size(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
let area = to.area();
|
||||||
|
Ok(self.min_size(area.wh().into())?
|
||||||
|
.map(|size|to.render_in(match *self {
|
||||||
|
Self::X(x, _) => [area.x() + x, area.y(), size.w(), size.h()],
|
||||||
|
Self::Y(y, _) => [area.x(), area.y() + y, size.w(), size.h()],
|
||||||
|
Self::XY(x, y, _) => [area.x() + x, area.y() + y, size.w(), size.h()],
|
||||||
|
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Pull<E, T> {
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn dx (&self) -> E::Unit {
|
||||||
|
match self {
|
||||||
|
Self::X(x, _) => *x,
|
||||||
|
Self::Y(_, _) => E::Unit::default(),
|
||||||
|
Self::XY(x, _, _) => *x,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn dy (&self) -> E::Unit {
|
||||||
|
match self {
|
||||||
|
Self::X(_, _) => E::Unit::default(),
|
||||||
|
Self::Y(y, _) => *y,
|
||||||
|
Self::XY(_, y, _) => *y,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Pull<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
self.inner().min_size(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
let area = to.area();
|
||||||
|
Ok(self.min_size(area.wh().into())?
|
||||||
|
.map(|size|to.render_in(match *self {
|
||||||
|
Self::X(x, _) => [area.x().minus(x), area.y(), size.w(), size.h()],
|
||||||
|
Self::Y(y, _) => [area.x(), area.y().minus(y), size.w(), size.h()],
|
||||||
|
Self::XY(x, y, _) => [area.x().minus(x), area.y().minus(y), size.w(), size.h()],
|
||||||
|
_ => unreachable!(),
|
||||||
|
}.into(), self.inner())).transpose()?.unwrap_or(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Padding<E, T> {
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, inner) => Push::x(*x, Shrink::x(*x, inner)),
|
||||||
|
Self::Y(y, inner) => Push::y(*y, Shrink::y(*y, inner)),
|
||||||
|
Self::XY(x, y, inner) => Push::xy(*x, *y, Shrink::xy(*x, *y, inner)),
|
||||||
|
}.render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Margin<E, T> {
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::X(_, i) => i,
|
||||||
|
Self::Y(_, i) => i,
|
||||||
|
Self::XY(_, _, i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Margin<E, T> {
|
||||||
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
match *self {
|
||||||
|
Self::X(x, ref inner) => Grow::x(x + x, inner),
|
||||||
|
Self::Y(y, ref inner) => Grow::y(y + y, inner),
|
||||||
|
Self::XY(x, y, ref inner) => Grow::xy(x + x, y + y, inner),
|
||||||
|
}.min_size(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
match *self {
|
||||||
|
Self::X(x, ref inner) => Push::x(x, inner),
|
||||||
|
Self::Y(y, ref inner) => Push::y(y, inner),
|
||||||
|
Self::XY(x, y, ref inner) => Push::xy(x, y, inner),
|
||||||
|
}.render(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Align<E, T> {
|
||||||
|
pub fn c (w: T) -> Self { Self::Center(w) }
|
||||||
|
pub fn x (w: T) -> Self { Self::X(w) }
|
||||||
|
pub fn y (w: T) -> Self { Self::Y(w) }
|
||||||
|
pub fn n (w: T) -> Self { Self::N(w) }
|
||||||
|
pub fn s (w: T) -> Self { Self::S(w) }
|
||||||
|
pub fn e (w: T) -> Self { Self::E(w) }
|
||||||
|
pub fn w (w: T) -> Self { Self::W(w) }
|
||||||
|
pub fn nw (w: T) -> Self { Self::NW(w) }
|
||||||
|
pub fn sw (w: T) -> Self { Self::SW(w) }
|
||||||
|
pub fn ne (w: T) -> Self { Self::NE(w) }
|
||||||
|
pub fn se (w: T) -> Self { Self::SE(w) }
|
||||||
|
pub fn inner (&self) -> &T {
|
||||||
|
match self {
|
||||||
|
Self::Center(inner) => inner,
|
||||||
|
Self::X(inner) => inner,
|
||||||
|
Self::Y(inner) => inner,
|
||||||
|
Self::NW(inner) => inner,
|
||||||
|
Self::N(inner) => inner,
|
||||||
|
Self::NE(inner) => inner,
|
||||||
|
Self::W(inner) => inner,
|
||||||
|
Self::E(inner) => inner,
|
||||||
|
Self::SW(inner) => inner,
|
||||||
|
Self::S(inner) => inner,
|
||||||
|
Self::SE(inner) => inner,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align<E: Engine, T: Render<E>, N: Coordinate, R: Area<N> + From<[N;4]>> (align: &Align<E, T>, outer: R, inner: R) -> Option<R> {
|
||||||
|
if outer.w() < inner.w() || outer.h() < inner.h() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let [ox, oy, ow, oh] = outer.xywh();
|
||||||
|
let [ix, iy, iw, ih] = inner.xywh();
|
||||||
|
Some(match align {
|
||||||
|
Align::Center(_) => [ox + (ow - iw) / 2.into(), oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||||
|
Align::X(_) => [ox + (ow - iw) / 2.into(), iy, iw, ih,].into(),
|
||||||
|
Align::Y(_) => [ix, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||||
|
Align::NW(_) => [ox, oy, iw, ih,].into(),
|
||||||
|
Align::N(_) => [ox + (ow - iw) / 2.into(), oy, iw, ih,].into(),
|
||||||
|
Align::NE(_) => [ox + ow - iw, oy, iw, ih,].into(),
|
||||||
|
Align::W(_) => [ox, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||||
|
Align::E(_) => [ox + ow - iw, oy + (oh - ih) / 2.into(), iw, ih,].into(),
|
||||||
|
Align::SW(_) => [ox, oy + oh - ih, iw, ih,].into(),
|
||||||
|
Align::S(_) => [ox + (ow - iw) / 2.into(), oy + oh - ih, iw, ih,].into(),
|
||||||
|
Align::SE(_) => [ox + ow - iw, oy + oh - ih, iw, ih,].into(),
|
||||||
|
_ => unreachable!()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine, T: Render<E>> Render<E> for Align<E, T> {
|
||||||
|
fn min_size (&self, outer_area: E::Size) -> Perhaps<E::Size> {
|
||||||
|
self.inner().min_size(outer_area)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
let outer_area = to.area();
|
||||||
|
Ok(if let Some(inner_size) = self.min_size(outer_area.wh().into())? {
|
||||||
|
let inner_area = outer_area.clip(inner_size);
|
||||||
|
if let Some(aligned) = align(&self, outer_area.into(), inner_area.into()) {
|
||||||
|
to.render_in(aligned, self.inner())?
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
42
layout/src/tui.rs
Normal file
42
layout/src/tui.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
use crate::*;
|
||||||
|
use ratatui::prelude::{Style, Color};
|
||||||
|
|
||||||
|
impl Render<Tui> for Measure<Tui> {
|
||||||
|
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||||
|
Ok(Some([0u16.into(), 0u16.into()].into()))
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
||||||
|
self.set_w(to.area().w());
|
||||||
|
self.set_h(to.area().h());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Measure<Tui> {
|
||||||
|
pub fn debug (&self) -> ShowMeasure {
|
||||||
|
ShowMeasure(&self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render!(<Tui>|self: ShowMeasure<'a>|render(|to: &mut TuiOutput|Ok({
|
||||||
|
let w = self.0.w();
|
||||||
|
let h = self.0.h();
|
||||||
|
to.blit(&format!(" {w} x {h} "), to.area.x(), to.area.y(), Some(
|
||||||
|
Style::default().bold().italic().bg(Color::Rgb(255, 0, 255)).fg(Color::Rgb(0,0,0))
|
||||||
|
))
|
||||||
|
})));
|
||||||
|
|
||||||
|
pub struct ShowMeasure<'a>(&'a Measure<Tui>);
|
||||||
|
|
||||||
|
pub struct DebugOverlay<E: Engine, W: Render<E>>(PhantomData<E>, pub W);
|
||||||
|
|
||||||
|
impl<T: Render<Tui>> Render<Tui> for DebugOverlay<Tui, T> {
|
||||||
|
fn min_size (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
|
||||||
|
self.1.min_size(to)
|
||||||
|
}
|
||||||
|
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
||||||
|
let [x, y, w, h] = to.area();
|
||||||
|
self.1.render(to)?;
|
||||||
|
Ok(to.blit(&format!("{w}x{h}+{x}+{y}"), x, y, Some(Style::default().green())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -47,13 +47,11 @@ pub mod plugin; pub use self::plugin::*;
|
||||||
pub mod pool; pub use self::pool::*;
|
pub mod pool; pub use self::pool::*;
|
||||||
pub mod sampler; pub use self::sampler::*;
|
pub mod sampler; pub use self::sampler::*;
|
||||||
pub mod sequencer; pub use self::sequencer::*;
|
pub mod sequencer; pub use self::sequencer::*;
|
||||||
pub mod space; pub use self::space::*;
|
|
||||||
pub mod status; pub use self::status::*;
|
pub mod status; pub use self::status::*;
|
||||||
pub mod style; pub use self::theme::*;
|
pub mod style; pub use self::theme::*;
|
||||||
pub mod theme; pub use self::theme::*;
|
pub mod theme; pub use self::theme::*;
|
||||||
pub mod time; pub use self::time::*;
|
pub mod time; pub use self::time::*;
|
||||||
pub mod transport; pub use self::transport::*;
|
pub mod transport; pub use self::transport::*;
|
||||||
pub mod tui; pub use self::tui::*;
|
|
||||||
|
|
||||||
pub use ::atomic_float;
|
pub use ::atomic_float;
|
||||||
pub(crate) use atomic_float::*;
|
pub(crate) use atomic_float::*;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use super::*;
|
|
||||||
|
|
||||||
impl<E: Engine, A: Render<E>> Render<E> for When<E, A> {
|
impl<E: Engine, A: Render<E>> Render<E> for When<E, A> {
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue