arranger, transport: despaghettify

This commit is contained in:
🪞👃🪞 2024-08-21 20:09:23 +03:00
parent 33bdf65e8d
commit 1104093395
10 changed files with 430 additions and 253 deletions

View file

@ -53,6 +53,7 @@ submod! {
render_border
render_collect
render_fill
render_layered
render_split
render_theme
time_base

View file

@ -2,10 +2,9 @@
use crate::*;
pub(crate) use ratatui::prelude::CrosstermBackend;
pub(crate) use ratatui::style::{Stylize, Style, Color};
pub(crate) use ratatui::style::Style;
pub(crate) use ratatui::layout::Rect;
pub(crate) use ratatui::buffer::{Buffer, Cell};
use ratatui::widgets::WidgetRef;
/// Main thread render loop
pub fn render_thread (
@ -37,7 +36,7 @@ pub fn render_thread (
}
/// Trait for things that render to the display.
pub trait Render {
pub trait Render: Send + Sync {
// Render something to an area of the buffer.
// Returns area used by component.
// This is insufficient but for the most basic dynamic layout algorithms.
@ -76,23 +75,23 @@ impl Render for () {
}
}
//impl<T: Render> Render for &T {
//fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
//(*self).render(buf, area)
//}
//fn into_collected <'a> (self) -> Collected<'a> where Self: Sized + 'a {
//Collected::Ref(self)
//}
//}
impl<T: Render> Render for &T {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
(*self).render(buf, area)
}
fn into_collected <'a> (self) -> Collected<'a> where Self: Sized + 'a {
Collected::Ref(self)
}
}
//impl<T: Render> Render for &mut T {
//fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
//(**self).render(buf, area)
//}
//fn into_collected <'a> (self) -> Collected<'a> where Self: Sized + 'a {
//Collected::Ref(self)
//}
//}
impl<T: Render> Render for &mut T {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
(**self).render(buf, area)
}
fn into_collected <'a> (self) -> Collected<'a> where Self: Sized + 'a {
Collected::Ref(self)
}
}
impl<T: Render> Render for Option<T> {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
@ -112,18 +111,18 @@ impl<'a> Render for Box<dyn Render + 'a> {
}
}
impl<'a, T: Fn(&mut Buffer, Rect) -> Usually<Rect> + Send + Sync + 'a> Render for T {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
(*self)(b, a)
}
}
//impl<'a> Render for Box<dyn Fn(&mut Buffer, Rect) -> Usually<Rect> + Send + Sync + 'a> {
//impl<'a, T: Fn(&mut Buffer, Rect) -> Usually<Rect> + Send + Sync + 'a> Render for T {
//fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
//(*self)(b, a)
//}
//}
impl<'a> Render for Box<dyn Fn(&mut Buffer, Rect) -> Usually<Rect> + Send + Sync + 'a> {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
(*self)(b, a)
}
}
impl<T: Render> Render for Arc<Mutex<T>> {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
self.lock().unwrap().render(b, a)
@ -203,17 +202,6 @@ impl BigBuffer {
}
}
pub struct Layered<'a, const N: usize>(pub [&'a (dyn Render + Sync); N]);
impl<'a, const N: usize> Render for Layered<'a, N> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
for layer in self.0.iter() {
layer.render(buf, area)?;
}
Ok(area)
}
}
pub struct If<'a>(pub bool, pub &'a (dyn Render + Sync));
impl<'a> Render for If<'a> {

View file

@ -16,7 +16,7 @@ impl<'a> Render for Collected<'a> {
}
}
pub struct Collection<'a>(Vec<Collected<'a>>);
pub struct Collection<'a>(pub Vec<Collected<'a>>);
impl<'a> Collection<'a> {
pub fn new () -> Self {
@ -27,6 +27,9 @@ impl<'a> Collection<'a> {
pub trait Collect<'a> {
fn add_box (self, item: Box<dyn Render + 'a>) -> Self;
fn add_ref (self, item: &'a dyn Render) -> Self;
fn add <T: Render + Sized + 'a> (self, item: T) -> Self where Self: Sized {
self.add_box(Box::new(item))
}
}
impl<'a> Collect<'a> for Collection<'a> {

View file

@ -0,0 +1,29 @@
use crate::*;
pub struct Layered<'a>(Collection<'a>);
impl<'a> Layered<'a> {
pub fn new () -> Self {
Self(Collection::new())
}
}
impl<'a> Render for Layered<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
for layer in self.0.0.iter() {
layer.render(buf, area)?;
}
Ok(area)
}
}
impl<'a> Collect<'a> for Layered<'a> {
fn add_box (mut self, item: Box<dyn Render + 'a>) -> Self {
self.0 = self.0.add_box(item);
self
}
fn add_ref (mut self, item: &'a dyn Render) -> Self {
self.0 = self.0.add_ref(item);
self
}
}

View file

@ -9,9 +9,9 @@ pub enum Direction {
}
impl Direction {
pub fn split <'a, const N: usize> (&self, items: [&'a (dyn Render + Sync);N]) -> Split<'a, N> {
Split(*self, items)
}
//pub fn split <'a, const N: usize> (&self, items: [&'a (dyn Render + Sync);N]) -> Split<'a, N> {
//Split(*self, items)
//}
pub fn split_focus <'a> (&self, index: usize, items: Renderables<'a>, style: Style) -> SplitFocus<'a> {
SplitFocus(*self, index, items, style)
}
@ -23,26 +23,27 @@ impl Direction {
}
}
pub struct Split<'a, const N: usize>(
pub Direction, pub [&'a (dyn Render + Sync);N]
);
pub struct Split<'a>(Collection<'a>, Direction);
impl<'a, const N: usize> Split<'a, N> {
pub fn down (items: [&'a (dyn Render + Sync);N]) -> Self {
Self(Direction::Down, items)
impl<'a> Split<'a> {
pub fn new (direction: Direction) -> Self {
Self(Collection::new(), direction)
}
pub fn right (items: [&'a (dyn Render + Sync);N]) -> Self {
Self(Direction::Right, items)
pub fn down () -> Self {
Self(Collection::new(), Direction::Down)
}
pub fn right () -> Self {
Self(Collection::new(), Direction::Right)
}
pub fn render_areas (&self, buf: &mut Buffer, area: Rect) -> Usually<(Rect, Vec<Rect>)> {
let Rect { mut x, mut y, mut width, mut height } = area;
let mut areas = vec![];
for item in self.1 {
for item in self.0.0.iter() {
if width == 0 || height == 0 {
break
}
let result = item.render(buf, Rect { x, y, width, height })?;
match self.0 {
match self.1 {
Direction::Down => {
y = y + result.height;
height = height.saturating_sub(result.height);
@ -59,12 +60,65 @@ impl<'a, const N: usize> Split<'a, N> {
}
}
impl<'a, const N: usize> Render for Split<'a, N> {
impl<'a> Render for Split<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
Ok(self.render_areas(buf, area)?.0)
}
}
impl<'a> Collect<'a> for Split<'a> {
fn add_box (mut self, item: Box<dyn Render + 'a>) -> Self {
self.0 = self.0.add_box(item);
self
}
fn add_ref (mut self, item: &'a dyn Render) -> Self {
self.0 = self.0.add_ref(item);
self
}
}
//pub struct Split<'a, const N: usize>(
//pub Direction, pub [&'a (dyn Render + Sync);N]
//);
//impl<'a, const N: usize> Split<'a, N> {
//pub fn down (items: [&'a (dyn Render + Sync);N]) -> Self {
//Self(Direction::Down, items)
//}
//pub fn right (items: [&'a (dyn Render + Sync);N]) -> Self {
//Self(Direction::Right, items)
//}
//pub fn render_areas (&self, buf: &mut Buffer, area: Rect) -> Usually<(Rect, Vec<Rect>)> {
//let Rect { mut x, mut y, mut width, mut height } = area;
//let mut areas = vec![];
//for item in self.1 {
//if width == 0 || height == 0 {
//break
//}
//let result = item.render(buf, Rect { x, y, width, height })?;
//match self.0 {
//Direction::Down => {
//y = y + result.height;
//height = height.saturating_sub(result.height);
//},
//Direction::Right => {
//x = x + result.width;
//width = width.saturating_sub(result.width);
//},
//_ => unimplemented!()
//};
//areas.push(area);
//}
//Ok((area, areas))
//}
//}
//impl<'a, const N: usize> Render for Split<'a, N> {
//fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
//Ok(self.render_areas(buf, area)?.0)
//}
//}
type Renderables<'a> = &'a [&'a (dyn Render + Send + Sync)];
pub struct SplitFocus<'a>(pub Direction, pub usize, pub Renderables<'a>, pub Style);

View file

@ -1,4 +1,5 @@
use crate::*;
use ratatui::style::Modifier;
pub trait Theme {
const BG0: Color;
@ -69,3 +70,75 @@ impl Theme for Nord {
const PLAYING: Color = Color::Rgb(60, 100, 50);
const SEPARATOR: Color = Color::Rgb(0, 0, 0);
}
pub const GRAY: Style = Style {
fg: Some(Color::Gray),
bg: None,
underline_color: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::empty(),
};
pub const GRAY_NOT_DIM: Style = Style {
fg: Some(Color::Gray),
bg: None,
underline_color: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::DIM,
};
pub const DIM: Style = Style {
fg: None,
bg: None,
underline_color: None,
add_modifier: Modifier::DIM,
sub_modifier: Modifier::empty(),
};
pub const GRAY_DIM: Style = Style {
fg: Some(Color::Gray),
bg: None,
underline_color: None,
add_modifier: Modifier::DIM,
sub_modifier: Modifier::empty(),
};
pub const WHITE_NOT_DIM_BOLD: Style = Style {
fg: Some(Color::White),
bg: None,
underline_color: None,
add_modifier: Modifier::BOLD,
sub_modifier: Modifier::DIM,
};
pub const GRAY_NOT_DIM_BOLD: Style = Style {
fg: Some(Color::Gray),
bg: None,
underline_color: None,
add_modifier: Modifier::BOLD,
sub_modifier: Modifier::DIM,
};
pub const NOT_DIM: Style = Style {
fg: None,
bg: None,
underline_color: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::DIM,
};
pub const NOT_DIM_GREEN: Style = Style {
fg: Some(Color::Green),
bg: None,
underline_color: None,
add_modifier: Modifier::BOLD,
sub_modifier: Modifier::DIM,
};
pub const NOT_DIM_BOLD: Style = Style {
fg: None,
bg: None,
underline_color: None,
add_modifier: Modifier::BOLD,
sub_modifier: Modifier::DIM,
};