From 14d619a10a99b73f883b80f78fe3aa8b522a3d1c Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 5 Sep 2024 13:28:05 +0300 Subject: [PATCH] wip: tui cleanup --- crates/tek_core/src/component.rs | 7 + .../tek_core/src/{ => component}/collect.rs | 5 + .../layered.rs} | 12 +- crates/tek_core/src/component/offset.rs | 38 +++ crates/tek_core/src/component/split.rs | 50 ++++ crates/tek_core/src/lib.rs | 6 +- crates/tek_core/src/render_buffer.rs | 25 -- crates/tek_core/src/render_split.rs | 96 ------- .../tek_core/src/{render_axis.rs => space.rs} | 1 + crates/tek_core/src/tui.rs | 264 +++++++++++------- crates/tek_mixer/src/mixer.rs | 22 +- crates/tek_mixer/src/plugin.rs | 15 +- crates/tek_mixer/src/sampler.rs | 18 +- crates/tek_mixer/src/track.rs | 16 +- crates/tek_mixer/src/track_view.rs | 19 +- crates/tek_sequencer/src/arranger.rs | 10 +- crates/tek_sequencer/src/arranger_view_v.rs | 47 ++-- 17 files changed, 345 insertions(+), 306 deletions(-) rename crates/tek_core/src/{ => component}/collect.rs (99%) rename crates/tek_core/src/{render_layered.rs => component/layered.rs} (58%) create mode 100644 crates/tek_core/src/component/offset.rs create mode 100644 crates/tek_core/src/component/split.rs delete mode 100644 crates/tek_core/src/render_buffer.rs delete mode 100644 crates/tek_core/src/render_split.rs rename crates/tek_core/src/{render_axis.rs => space.rs} (99%) diff --git a/crates/tek_core/src/component.rs b/crates/tek_core/src/component.rs index 952a4d90..c9bf9e19 100644 --- a/crates/tek_core/src/component.rs +++ b/crates/tek_core/src/component.rs @@ -5,3 +5,10 @@ pub trait Component: Render + Handle {} /// Everything that implements [Render] and [Handle] is a [Component]. impl + Handle> Component for C {} + +submod! { + collect + layered + offset + split +} diff --git a/crates/tek_core/src/collect.rs b/crates/tek_core/src/component/collect.rs similarity index 99% rename from crates/tek_core/src/collect.rs rename to crates/tek_core/src/component/collect.rs index df77d585..05ef4971 100644 --- a/crates/tek_core/src/collect.rs +++ b/crates/tek_core/src/component/collect.rs @@ -4,6 +4,7 @@ pub enum Collected<'a, E: Engine> { Box(Box + 'a>), Ref(&'a (dyn Render + 'a)), } + impl<'a, E: Engine> Render for Collected<'a, E> { fn render (&self, to: &mut E) -> Perhaps { match self { @@ -12,14 +13,17 @@ impl<'a, E: Engine> Render for Collected<'a, E> { } } } + pub struct Collection<'a, E: Engine>( pub Vec> ); + impl<'a, E: Engine> Collection<'a, E> { pub fn new () -> Self { Self(vec![]) } } + pub trait Collect<'a, E: Engine> { fn add_box (self, item: Box + 'a>) -> Self; fn add_ref (self, item: &'a dyn Render) -> Self; @@ -29,6 +33,7 @@ pub trait Collect<'a, E: Engine> { self.add_box(Box::new(item)) } } + impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> { fn add_box (mut self, item: Box + 'a>) -> Self { self.0.push(Collected::Box(item)); diff --git a/crates/tek_core/src/render_layered.rs b/crates/tek_core/src/component/layered.rs similarity index 58% rename from crates/tek_core/src/render_layered.rs rename to crates/tek_core/src/component/layered.rs index 92fe0546..b892ec8b 100644 --- a/crates/tek_core/src/render_layered.rs +++ b/crates/tek_core/src/component/layered.rs @@ -1,6 +1,6 @@ use crate::*; -pub struct Layered<'a, E: Engine>(Collection<'a, E>); +pub struct Layered<'a, E: Engine>(pub Collection<'a, E>); impl<'a, E: Engine> Layered<'a, E> { pub fn new () -> Self { @@ -18,13 +18,3 @@ impl<'a, E: Engine> Collect<'a, E> for Layered<'a, E> { self } } - -impl<'a> Render for Layered<'a, Tui> { - fn render (&self, to: &mut Tui) -> Perhaps { - let area = to.area(); - for layer in self.0.0.iter() { - layer.render(to)?; - } - Ok(Some(area)) - } -} diff --git a/crates/tek_core/src/component/offset.rs b/crates/tek_core/src/component/offset.rs new file mode 100644 index 00000000..aeaa69a1 --- /dev/null +++ b/crates/tek_core/src/component/offset.rs @@ -0,0 +1,38 @@ +use crate::*; +use std::ops::Add; + +pub struct Offset(pub N, pub N); + +impl From for Offset { + fn from (n: N) -> Self { + Self(n, n) + } +} + +pub struct Inset(pub N, pub N, pub N, pub N); + +impl From for Inset { + fn from (n: N) -> Self { + Self(n, n, n, n) + } +} + +impl From<(N, N)> for Inset { + fn from ((n1, n2): (N, N)) -> Self { + Self(n1, n2, n1, n2) + } +} + +pub struct Outset(pub N, pub N, pub N, pub N); + +impl From for Outset { + fn from (n: N) -> Self { + Self(n, n, n, n) + } +} + +impl From<(N, N)> for Outset { + fn from ((n1, n2): (N, N)) -> Self { + Self(n1, n2, n1, n2) + } +} diff --git a/crates/tek_core/src/component/split.rs b/crates/tek_core/src/component/split.rs new file mode 100644 index 00000000..8cf2f667 --- /dev/null +++ b/crates/tek_core/src/component/split.rs @@ -0,0 +1,50 @@ +use crate::*; + +#[derive(Copy, Clone)] +pub enum Direction { Up, Down, Left, Right } + +impl Direction { + pub fn is_down (&self) -> bool { + match self { Self::Down => true, _ => false } + } + pub fn is_right (&self) -> bool { + match self { Self::Right => true, _ => false } + } +} + +pub struct Split<'a, E: Engine> { + items: Collection<'a, E>, + direction: Direction, + focus: Option +} + +impl<'a, E: Engine> Split<'a, E> { + pub fn new (direction: Direction) -> Self { + Self { + items: Collection::new(), + direction, + focus: None + } + } + pub fn down () -> Self { + Self::new(Direction::Down) + } + pub fn right () -> Self { + Self::new(Direction::Right) + } + pub fn focus (mut self, focus: Option) -> Self { + self.focus = focus; + self + } +} + +impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> { + fn add_box (mut self, item: Box + 'a>) -> Self { + self.items = self.items.add_box(item); + self + } + fn add_ref (mut self, item: &'a dyn Render) -> Self { + self.items = self.items.add_ref(item); + self + } +} diff --git a/crates/tek_core/src/lib.rs b/crates/tek_core/src/lib.rs index 83f73d12..74958ee6 100644 --- a/crates/tek_core/src/lib.rs +++ b/crates/tek_core/src/lib.rs @@ -27,7 +27,6 @@ use better_panic::{Settings, Verbosity}; } submod! { - collect component edn engine @@ -40,11 +39,8 @@ submod! { jack_event jack_ports keymap + space render - render_axis - render_buffer - render_layered - render_split time tui } diff --git a/crates/tek_core/src/render_buffer.rs b/crates/tek_core/src/render_buffer.rs deleted file mode 100644 index 824d0202..00000000 --- a/crates/tek_core/src/render_buffer.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::*; - -#[derive(Default)] -pub struct BigBuffer { - pub width: usize, - pub height: usize, - pub content: Vec -} - -impl BigBuffer { - pub fn new (width: usize, height: usize) -> Self { - Self { width, height, content: vec![Cell::default(); width*height] } - } - pub fn get (&self, x: usize, y: usize) -> Option<&Cell> { - let i = self.index_of(x, y); - self.content.get(i) - } - pub fn get_mut (&mut self, x: usize, y: usize) -> Option<&mut Cell> { - let i = self.index_of(x, y); - self.content.get_mut(i) - } - pub fn index_of (&self, x: usize, y: usize) -> usize { - y * self.width + x - } -} diff --git a/crates/tek_core/src/render_split.rs b/crates/tek_core/src/render_split.rs deleted file mode 100644 index b7e07821..00000000 --- a/crates/tek_core/src/render_split.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::*; - -#[derive(Copy, Clone)] -pub enum Direction { - Up, - Down, - Left, - Right -} - -impl Direction { - pub fn is_down (&self) -> bool { - match self { Self::Down => true, _ => false } - } - pub fn is_right (&self) -> bool { - match self { Self::Right => true, _ => false } - } -} - -pub struct Split<'a, E: Engine> { - items: Collection<'a, E>, - direction: Direction, - focus: Option -} - -impl<'a, E: Engine> Split<'a, E> { - pub fn new (direction: Direction) -> Self { - Self { - items: Collection::new(), - direction, - focus: None - } - } - pub fn down () -> Self { - Self::new(Direction::Down) - } - pub fn right () -> Self { - Self::new(Direction::Right) - } - pub fn focus (mut self, focus: Option) -> Self { - self.focus = focus; - self - } -} - -impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> { - fn add_box (mut self, item: Box + 'a>) -> Self { - self.items = self.items.add_box(item); - self - } - fn add_ref (mut self, item: &'a dyn Render) -> Self { - self.items = self.items.add_ref(item); - self - } -} - -impl<'a> Render for Split<'a, Tui> { - fn render (&self, to: &mut Tui) -> Perhaps { - Ok(None)//Rect::default())//Some(self.render_areas(to)?.0)) - } -} - -impl<'a> Split<'a, Tui> { - pub fn render_areas (&self, to: &mut Tui) -> Usually<(Rect, Vec)> { - Ok((Rect::default(), vec![])) - //let Rect { mut x, mut y, mut width, mut height } = to.area; - //let TuiOutput { buffer, area } = to; - //let mut areas = vec![]; - //for (index, item) in self.items.0.iter().enumerate() { - //if width == 0 || height == 0 { - //break - //} - //if let Some(result) = item.render(&mut TuiOutput { - //buffer: to.buffer, - //area: Rect { x, y, width, height } - //})? { - //match self.direction { - //Direction::Down => { - //y += result.height; - //height = height.saturating_sub(result.height); - //}, - //Direction::Right => { - //x += result.width; - //width = width.saturating_sub(result.width); - //}, - //_ => unimplemented!() - //}; - //areas.push(result); - //if self.focus == Some(index) { - //Corners(Style::default().green().not_dim()).draw(to.buffer, result)?; - //} - //} - //} - //Ok((to.area, areas)) - } -} diff --git a/crates/tek_core/src/render_axis.rs b/crates/tek_core/src/space.rs similarity index 99% rename from crates/tek_core/src/render_axis.rs rename to crates/tek_core/src/space.rs index 0a0c5055..920749b9 100644 --- a/crates/tek_core/src/render_axis.rs +++ b/crates/tek_core/src/space.rs @@ -31,3 +31,4 @@ impl ScaledAxis { self.scale = cb(self.scale) } } + diff --git a/crates/tek_core/src/tui.rs b/crates/tek_core/src/tui.rs index a5fcc4fb..af16b1db 100644 --- a/crates/tek_core/src/tui.rs +++ b/crates/tek_core/src/tui.rs @@ -1,5 +1,4 @@ use crate::*; - pub(crate) use ratatui::buffer::Cell; pub(crate) use crossterm::{ExecutableCommand}; pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers}; @@ -11,7 +10,6 @@ use crossterm::terminal::{ EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode }; - pub struct Tui { exited: Arc, buffer: usize, @@ -28,11 +26,18 @@ impl Engine for Tui { self.exited.fetch_and(true, Ordering::Relaxed) } fn setup (&mut self) -> Usually<()> { - panic_hook_setup(); - terminal_setup() + let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler(); + std::panic::set_hook(Box::new(move |info: &std::panic::PanicInfo|{ + stdout().execute(LeaveAlternateScreen).unwrap(); + disable_raw_mode().unwrap(); + better_panic_handler(info); + })); + stdout().execute(EnterAlternateScreen)?; + enable_raw_mode().map_err(Into::into) } fn teardown (&mut self) -> Usually<()> { - terminal_teardown() + stdout().execute(LeaveAlternateScreen)?; + disable_raw_mode().map_err(Into::into) } fn handle (&self, state: &mut impl Handle) -> Usually<()> { if ::crossterm::event::poll(self.poll).is_ok() { @@ -49,6 +54,7 @@ impl Engine for Tui { } fn render (&mut self, state: &impl Render) -> Usually<()> { state.render(self).expect("render failed"); + self.flip(); Ok(()) } } @@ -96,10 +102,6 @@ impl Tui { main_thread.join().expect("main thread failed"); Ok(state) } - pub fn target <'a> (&'a mut self) -> impl TuiTarget + 'a { - let area = self.area(); - (self.buffer(), area) - } fn flip (&mut self) { let previous_buffer = &self.buffers[1 - self.buffer]; let current_buffer = &self.buffers[self.buffer]; @@ -108,6 +110,24 @@ impl Tui { self.buffers[1 - self.buffer].reset(); self.buffer = 1 - self.buffer; } + pub fn area (&self) -> Rect { + self.area + } + pub fn buffer (&mut self) -> &mut Buffer { + &mut self.buffers[self.buffer] + } + pub fn buffer_update (&mut self, area: Rect, callback: &impl Fn(&mut Cell, u16, u16)) { + let buf = self.buffer(); + 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_bg (&mut self, area: Rect, color: Color) { self.buffer_update(area, &|cell,_,_|{cell.set_bg(color);}) } @@ -130,80 +150,24 @@ impl Tui { cell.modifier = ratatui::style::Modifier::DIM; } } - pub fn buffer_update (&mut self, area: Rect, callback: &impl Fn(&mut Cell, u16, u16)) { + pub fn blit ( + &mut self, text: &impl AsRef, x: u16, y: u16, style: Option