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
|
|
@ -36,14 +36,14 @@ pub trait Coordinate: Send + Sync + Copy
|
|||
+ Into<usize>
|
||||
+ Into<f64>
|
||||
{
|
||||
fn minus (self, other: Self) -> Self {
|
||||
#[inline] fn minus (self, other: Self) -> Self {
|
||||
if self >= other {
|
||||
self - other
|
||||
} else {
|
||||
0.into()
|
||||
}
|
||||
}
|
||||
fn zero () -> Self {
|
||||
#[inline] fn zero () -> Self {
|
||||
0.into()
|
||||
}
|
||||
}
|
||||
|
|
@ -65,11 +65,21 @@ 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 {
|
||||
fn x (&self) -> N;
|
||||
fn y (&self) -> N;
|
||||
fn w (&self) -> N;
|
||||
fn h (&self) -> N;
|
||||
fn x (&self) -> N;
|
||||
fn y (&self) -> N;
|
||||
fn w (&self) -> N;
|
||||
fn h (&self) -> N;
|
||||
#[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
|
||||
if self.w() < w || self.h() < h {
|
||||
Err(format!("min {w}x{h}").into())
|
||||
|
|
@ -77,4 +87,33 @@ pub trait Area<N: Coordinate>: Copy {
|
|||
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 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.
|
||||
pub trait Render<E: Engine>: Send + Sync {
|
||||
/// Minimum size to use
|
||||
|
|
@ -18,18 +50,18 @@ pub trait Content<E: Engine>: Send + Sync {
|
|||
fn content (&self) -> Option<impl Render<E>>;
|
||||
}
|
||||
|
||||
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>> 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(()))
|
||||
//}
|
||||
//}
|
||||
|
||||
/// Rendering target
|
||||
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 &mut 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 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 Mutex<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 {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
(*self).min_size(to)
|
||||
|
|
|
|||
|
|
@ -25,18 +25,6 @@ pub(crate) use ratatui::{
|
|||
|
||||
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 exited: Arc<AtomicBool>,
|
||||
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 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 {
|
||||
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]))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue