wip: broken collect enum

This commit is contained in:
🪞👃🪞 2024-08-21 16:46:31 +03:00
parent bb0230b6e5
commit 72f47bc837
6 changed files with 301 additions and 157 deletions

View file

@ -49,7 +49,10 @@ submod! {
jack_event
jack_ports
render
render_axis
render_border
render_collect
render_fill
render_split
render_theme
time_base

View file

@ -36,86 +36,17 @@ pub fn render_thread (
}))
}
pub fn make_dim (buf: &mut Buffer) {
for cell in buf.content.iter_mut() {
cell.bg = ratatui::style::Color::Rgb(30,30,30);
cell.fg = ratatui::style::Color::Rgb(100,100,100);
cell.modifier = ratatui::style::Modifier::DIM;
}
}
pub fn center_box (area: Rect, w: u16, h: u16) -> Rect {
let width = w.min(area.width * 3 / 5);
let height = h.min(area.width * 3 / 5);
let x = area.x + (area.width - width) / 2;
let y = area.y + (area.height - height) / 2;
Rect { x, y, width, height }
}
pub fn buffer_update (
buf: &mut Buffer, area: Rect, callback: &impl Fn(&mut Cell, u16, u16)
) {
for row in 0..area.height {
let y = area.y + row;
for col in 0..area.width {
let x = area.x + col;
if x < buf.area.width && y < buf.area.height {
callback(buf.get_mut(x, y), col, row);
}
}
}
}
pub fn fill_fg (buf: &mut Buffer, area: Rect, color: Color) {
buffer_update(buf, area, &|cell,_,_|{cell.set_fg(color);})
}
pub fn fill_bg (buf: &mut Buffer, area: Rect, color: Color) {
buffer_update(buf, area, &|cell,_,_|{cell.set_bg(color);})
}
pub fn to_fill_bg (color: Color) -> impl Render {
move |buf: &mut Buffer, area: Rect|{
fill_bg(buf, area, color);
Ok(area)
}
}
pub fn fill_char (buf: &mut Buffer, area: Rect, c: char) {
buffer_update(buf, area, &|cell,_,_|{cell.set_char(c);})
}
pub fn half_block (lower: bool, upper: bool) -> Option<char> {
match (lower, upper) {
(true, true) => Some('█'),
(true, false) => Some('▄'),
(false, true) => Some('▀'),
_ => None
}
}
pub trait Blit {
// Render something to X, Y coordinates in a buffer, ignoring width/height.
fn blit (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect>;
}
impl<T: AsRef<str>> Blit for T {
fn blit (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect> {
if x < buf.area.width && y < buf.area.height {
buf.set_string(x, y, self.as_ref(), style.unwrap_or(Style::default()));
}
Ok(Rect { x, y, width: self.as_ref().len() as u16, height: 1 })
}
}
/// Trait for things that render to the display.
pub trait Render: Send {
pub trait Render {
// Render something to an area of the buffer.
// Returns area used by component.
// This is insufficient but for the most basic dynamic layout algorithms.
fn render (&self, _b: &mut Buffer, _a: Rect) -> Usually<Rect> {
Ok(Rect { x: 0, y: 0, width: 0, height: 0 })
}
fn into_collected <'a> (self) -> Collected<'a> where Self: Sized + 'a {
Collected::Box(Box::new(self))
}
}
/// Implement the `Render` trait.
@ -145,7 +76,25 @@ impl Render for () {
}
}
impl<T: Render + Send + Sync> Render for Option<&T> {
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 Option<T> {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
match self {
Some(widget) => widget.render(b, a),
@ -154,7 +103,16 @@ impl<T: Render + Send + Sync> Render for Option<&T> {
}
}
impl<T: Fn(&mut Buffer, Rect) -> Usually<Rect> + Send> Render for T {
impl Render for Box<dyn Render> {
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::Box(self)
}
}
impl Render for Box<dyn Fn(&mut Buffer, Rect) -> Usually<Rect> + Send + Sync> {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
(*self)(b, a)
}
@ -172,18 +130,49 @@ impl<T: Render + Sync> Render for Arc<RwLock<T>> {
}
}
impl WidgetRef for &dyn Render {
fn render_ref (&self, area: Rect, buf: &mut Buffer) {
Render::render(*self, buf, area).expect("Failed to render device.");
pub fn center_box (area: Rect, w: u16, h: u16) -> Rect {
let width = w.min(area.width * 3 / 5);
let height = h.min(area.width * 3 / 5);
let x = area.x + (area.width - width) / 2;
let y = area.y + (area.height - height) / 2;
Rect { x, y, width, height }
}
pub fn half_block (lower: bool, upper: bool) -> Option<char> {
match (lower, upper) {
(true, true) => Some('█'),
(true, false) => Some('▄'),
(false, true) => Some('▀'),
_ => None
}
}
impl WidgetRef for dyn Render {
fn render_ref (&self, area: Rect, buf: &mut Buffer) {
Render::render(self, buf, area).expect("Failed to render device.");
pub trait Blit {
// Render something to X, Y coordinates in a buffer, ignoring width/height.
fn blit (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect>;
}
impl<T: AsRef<str>> Blit for T {
fn blit (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect> {
if x < buf.area.width && y < buf.area.height {
buf.set_string(x, y, self.as_ref(), style.unwrap_or(Style::default()));
}
Ok(Rect { x, y, width: self.as_ref().len() as u16, height: 1 })
}
}
//impl WidgetRef for &dyn Render {
//fn render_ref (&self, area: Rect, buf: &mut Buffer) {
//Render::render(*self, buf, area).expect("Failed to render device.");
//}
//}
//impl WidgetRef for dyn Render {
//fn render_ref (&self, area: Rect, buf: &mut Buffer) {
//Render::render(self, buf, area).expect("Failed to render device.");
//}
//}
#[derive(Default)]
pub struct BigBuffer {
pub width: usize,
@ -240,37 +229,3 @@ impl<'a> Render for IfElse<'a> {
}.render(buf, area)
}
}
macro_rules! impl_axis_common { ($A:ident $T:ty) => {
impl $A<$T> {
pub fn start_inc (&mut self) -> $T {
self.start = self.start + 1;
self.start
}
pub fn start_dec (&mut self) -> $T {
self.start = self.start.saturating_sub(1);
self.start
}
pub fn point_inc (&mut self) -> Option<$T> {
self.point = self.point.map(|p|p + 1);
self.point
}
pub fn point_dec (&mut self) -> Option<$T> {
self.point = self.point.map(|p|p.saturating_sub(1));
self.point
}
}
} }
pub struct FixedAxis<T> { pub start: T, pub point: Option<T> }
impl_axis_common!(FixedAxis u16);
impl_axis_common!(FixedAxis usize);
pub struct ScaledAxis<T> { pub start: T, pub scale: T, pub point: Option<T> }
impl_axis_common!(ScaledAxis u16);
impl_axis_common!(ScaledAxis usize);
impl<T: Copy> ScaledAxis<T> {
pub fn scale_mut (&mut self, cb: &impl Fn(T)->T) {
self.scale = cb(self.scale)
}
}

View file

@ -0,0 +1,35 @@
use crate::*;
macro_rules! impl_axis_common { ($A:ident $T:ty) => {
impl $A<$T> {
pub fn start_inc (&mut self) -> $T {
self.start = self.start + 1;
self.start
}
pub fn start_dec (&mut self) -> $T {
self.start = self.start.saturating_sub(1);
self.start
}
pub fn point_inc (&mut self) -> Option<$T> {
self.point = self.point.map(|p|p + 1);
self.point
}
pub fn point_dec (&mut self) -> Option<$T> {
self.point = self.point.map(|p|p.saturating_sub(1));
self.point
}
}
} }
pub struct FixedAxis<T> { pub start: T, pub point: Option<T> }
impl_axis_common!(FixedAxis u16);
impl_axis_common!(FixedAxis usize);
pub struct ScaledAxis<T> { pub start: T, pub scale: T, pub point: Option<T> }
impl_axis_common!(ScaledAxis u16);
impl_axis_common!(ScaledAxis usize);
impl<T: Copy> ScaledAxis<T> {
pub fn scale_mut (&mut self, cb: &impl Fn(T)->T) {
self.scale = cb(self.scale)
}
}

View file

@ -0,0 +1,41 @@
use crate::*;
pub enum Collected<'a> {
Box(Box<dyn Render + 'a>),
Ref(&'a (dyn Render + 'a)),
None
}
impl<'a> Render for Collected<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
Ok(match self {
Self::Box(item) => (*item).render(buf, area)?,
Self::Ref(item) => (*item).render(buf, area)?,
Self::None => ().render(buf, area)?
})
}
}
pub struct Collection<'a>(Vec<Collected<'a>>);
impl<'a> Collection<'a> {
pub fn new () -> Self {
Self(vec![])
}
}
pub trait Collect<'a> {
fn add_box (self, item: Box<dyn Render>) -> Self;
fn add_ref (self, item: &'a dyn Render) -> Self;
}
impl<'a> Collect<'a> for Collection<'a> {
fn add_box (mut self, item: Box<dyn Render>) -> Self {
self.0.push(Collected::Box(item));
self
}
fn add_ref (mut self, item: &'a dyn Render) -> Self {
self.0.push(Collected::Ref(item));
self
}
}

View file

@ -0,0 +1,42 @@
use crate::*;
pub struct FillBg(pub Color);
render!(FillBg |self, buf, area| {
fill_bg(buf, area, self.0);
Ok(area)
});
pub fn make_dim (buf: &mut Buffer) {
for cell in buf.content.iter_mut() {
cell.bg = ratatui::style::Color::Rgb(30,30,30);
cell.fg = ratatui::style::Color::Rgb(100,100,100);
cell.modifier = ratatui::style::Modifier::DIM;
}
}
pub fn buffer_update (
buf: &mut Buffer, area: Rect, callback: &impl Fn(&mut Cell, u16, u16)
) {
for row in 0..area.height {
let y = area.y + row;
for col in 0..area.width {
let x = area.x + col;
if x < buf.area.width && y < buf.area.height {
callback(buf.get_mut(x, y), col, row);
}
}
}
}
pub fn fill_fg (buf: &mut Buffer, area: Rect, color: Color) {
buffer_update(buf, area, &|cell,_,_|{cell.set_fg(color);})
}
pub fn fill_bg (buf: &mut Buffer, area: Rect, color: Color) {
buffer_update(buf, area, &|cell,_,_|{cell.set_bg(color);})
}
pub fn fill_char (buf: &mut Buffer, area: Rect, c: char) {
buffer_update(buf, area, &|cell,_,_|{cell.set_char(c);})
}