mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: broken collect enum
This commit is contained in:
parent
bb0230b6e5
commit
72f47bc837
6 changed files with 301 additions and 157 deletions
|
|
@ -49,7 +49,10 @@ submod! {
|
|||
jack_event
|
||||
jack_ports
|
||||
render
|
||||
render_axis
|
||||
render_border
|
||||
render_collect
|
||||
render_fill
|
||||
render_split
|
||||
render_theme
|
||||
time_base
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
35
crates/tek_core/src/render_axis.rs
Normal file
35
crates/tek_core/src/render_axis.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
41
crates/tek_core/src/render_collect.rs
Normal file
41
crates/tek_core/src/render_collect.rs
Normal 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
|
||||
}
|
||||
}
|
||||
42
crates/tek_core/src/render_fill.rs
Normal file
42
crates/tek_core/src/render_fill.rs
Normal 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);})
|
||||
}
|
||||
|
|
@ -20,8 +20,36 @@ impl ArrangerViewMode {
|
|||
}
|
||||
}
|
||||
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
struct Split<'a>(Collection<'a>, Direction);
|
||||
|
||||
impl<'a> Split<'a> {
|
||||
fn new (direction: Direction) -> Self {
|
||||
Self(Collection::new(), direction)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Render for Split<'a> {
|
||||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
Ok(area)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Collect<'a> for Split<'a> {
|
||||
fn add (mut self, item: Box<dyn Render>) -> Self {
|
||||
self.0 = self.0.add(item);
|
||||
self
|
||||
}
|
||||
fn add_ref (mut self, item: &'a dyn Render) -> Self {
|
||||
self.0 = self.0.add_ref(item);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
render!(Arranger |self, buf, area| {
|
||||
let arrangement = |buf: &mut Buffer, area: Rect| {
|
||||
|
||||
let arrangement = Box::new(|buf: &mut Buffer, area: Rect| {
|
||||
let area = Rect {
|
||||
x: area.x + 1, width: area.width - 2, y: area.y + 1, height: area.height - 2
|
||||
};
|
||||
|
|
@ -42,47 +70,87 @@ render!(Arranger |self, buf, area| {
|
|||
height: area.height + 2,
|
||||
};
|
||||
Lozenge(Style::default().fg(Nord::BG2)).draw(buf, area)
|
||||
};
|
||||
let area = if let Some(direction) = self.show_sequencer {
|
||||
let arrangement = arrangement(buf, area)?;
|
||||
match direction {
|
||||
Direction::Down => {
|
||||
let sequencer = if let Some(sequencer) = self.sequencer() {
|
||||
sequencer.render(buf, Rect {
|
||||
y: area.y + arrangement.height,
|
||||
height: area.height - arrangement.height,
|
||||
..area
|
||||
})?
|
||||
} else {
|
||||
Rect::default()
|
||||
};
|
||||
match self.focus_sequencer {
|
||||
true => {
|
||||
"[Arrows] Move, [A]dd, [D]elete, [R]ecord, [P]lay".blit(
|
||||
buf, area.x + 1, area.height - 1, Some(Style::default().dim())
|
||||
)?;
|
||||
},
|
||||
false => {
|
||||
"[Arrows] Move, [P]lay, [R]ecord, [N]ame, [E]dit, [C-T]rack add, [C-A]dd scene".blit(
|
||||
buf, area.x + 1, area.y + arrangement.height, Some(Style::default().dim())
|
||||
)?;
|
||||
},
|
||||
}
|
||||
Corners(Style::default().green().not_dim()).draw(buf, match self.focus_sequencer {
|
||||
true => sequencer,
|
||||
false => arrangement,
|
||||
})?;
|
||||
},
|
||||
_ => unimplemented!()
|
||||
}
|
||||
Ok(area)
|
||||
});
|
||||
|
||||
let mut layout = Split::new(Direction::Down)
|
||||
.add_ref(match &self.transport {
|
||||
Some(transport) => transport as &dyn Render,
|
||||
None => &() as &dyn Render
|
||||
});
|
||||
|
||||
if let Some(direction) = self.show_sequencer {
|
||||
layout = layout.add(Box::new(Split::new(direction)
|
||||
.add(arrangement)));
|
||||
} else {
|
||||
arrangement(buf, area)
|
||||
}?;
|
||||
if let Some(ref modal) = self.modal {
|
||||
fill_bg(buf, area, Nord::bg_lo(false, false));
|
||||
fill_fg(buf, area, Nord::bg_hi(false, false));
|
||||
modal.render(buf, area)?;
|
||||
layout = layout.add(arrangement);
|
||||
}
|
||||
Ok(area)
|
||||
|
||||
layout.render(buf, area)
|
||||
|
||||
//.add(if let Some(direction) = self.show_sequencer {
|
||||
//Box::new(Split::new(direction)
|
||||
//.add(arrangement))
|
||||
////.add_ref(&self.sequencer())) as Box<dyn Render>
|
||||
//} else {
|
||||
//Box::new(arrangement) as Box<dyn Render>
|
||||
//})
|
||||
//.render(buf, area)
|
||||
|
||||
|
||||
//Column([
|
||||
//self.transport,
|
||||
//match self.mode {
|
||||
//ArrangerViewMode::Horizontal =>
|
||||
//super::arranger_view_h::draw(self, buf, area),
|
||||
//ArrangerViewMode::VerticalCompact1 =>
|
||||
//super::arranger_view_v::draw_compact_1(self, buf, area),
|
||||
//ArrangerViewMode::VerticalCompact2 =>
|
||||
//super::arranger_view_v::draw_compact_2(self, buf, area),
|
||||
//ArrangerViewMode::VerticalExpanded =>
|
||||
//super::arranger_view_v::draw_expanded(self, buf, area),
|
||||
//},
|
||||
|
||||
|
||||
//let area = if let Some(direction) = self.show_sequencer {
|
||||
//let arrangement = arrangement(buf, area)?;
|
||||
//match direction {
|
||||
//Direction::Down => {
|
||||
//let sequencer = if let Some(sequencer) = self.sequencer() {
|
||||
//sequencer.render(buf, Rect {
|
||||
//y: area.y + arrangement.height,
|
||||
//height: area.height - arrangement.height,
|
||||
//..area
|
||||
//})?
|
||||
//} else {
|
||||
//Rect::default()
|
||||
//};
|
||||
//match self.focus_sequencer {
|
||||
//true => {
|
||||
//"[Arrows] Move, [A]dd, [D]elete, [R]ecord, [P]lay".blit(
|
||||
//buf, area.x + 1, area.height - 1, Some(Style::default().dim())
|
||||
//)?;
|
||||
//},
|
||||
//false => {
|
||||
//"[Arrows] Move, [P]lay, [R]ecord, [N]ame, [E]dit, [C-T]rack add, [C-A]dd scene".blit(
|
||||
//buf, area.x + 1, area.y + arrangement.height, Some(Style::default().dim())
|
||||
//)?;
|
||||
//},
|
||||
//}
|
||||
//Corners(Style::default().green().not_dim()).draw(buf, match self.focus_sequencer {
|
||||
//true => sequencer,
|
||||
//false => arrangement,
|
||||
//})?;
|
||||
//},
|
||||
//_ => unimplemented!()
|
||||
//}
|
||||
//Ok(area)
|
||||
//} else {
|
||||
//arrangement(buf, area)
|
||||
//}?;
|
||||
//if let Some(ref modal) = self.modal {
|
||||
//fill_bg(buf, area, Nord::bg_lo(false, false));
|
||||
//fill_fg(buf, area, Nord::bg_hi(false, false));
|
||||
//modal.render(buf, area)?;
|
||||
//}
|
||||
//Ok(area)
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue