From d02dbe5f3bdac2505f3af3b376e4a538d462cc71 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 14 Jul 2024 00:29:46 +0300 Subject: [PATCH] improve arranger navigation and higlighting --- src/devices/arranger.rs | 55 ++++++++++++++++++++++++++++++----------- src/view/chain.rs | 6 ++--- src/view/split.rs | 38 +++++++++++++++++----------- src/view/table.rs | 34 ------------------------- src/view/theme.rs | 10 ++++++++ 5 files changed, 76 insertions(+), 67 deletions(-) delete mode 100644 src/view/table.rs diff --git a/src/devices/arranger.rs b/src/devices/arranger.rs index 9416409d..3c519a36 100644 --- a/src/devices/arranger.rs +++ b/src/devices/arranger.rs @@ -120,12 +120,14 @@ impl Arranger { } fn draw_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually { + let bg_hi = Nord::bg_hier(self.focused, self.entered); + let bg_lo = Nord::bg_hi(self.focused, self.entered); return Split::right([ // Scene column &|buf: &mut Buffer, area: Rect|{ - let Rect { x, y, height, .. } = area; + let Rect { x, y, width, height } = area; for (scene_index, scene) in self.scenes.iter().enumerate() { if y + 2 * scene_index as u16 >= height { break @@ -140,6 +142,14 @@ impl Arranger { }); if playing { "" } else { " " }.blit(buf, x+1, y, style)?; scene.name.blit(buf, x + 2, y, style)?; + if self.selected.scene() == Some(scene_index) { + let bg = if self.selected == ArrangerFocus::Scene(scene_index) { + bg_hi + } else { + bg_lo + }; + fill_bg(buf, Rect { x, y, width, height: 2 }, bg) + } } let width = 2 + self.scenes.iter() .map(|x|&x.name).fold(0, |x,y|x.max(y.len() as u16+1)); @@ -155,7 +165,6 @@ impl Arranger { } let width = 16u16; track.name.blit(buf, x, y, Some(Style::default().bold()))?; - let bg = Nord::bg_hi(self.focused, self.entered); for (scene_index, scene) in self.scenes.iter().enumerate() { if y + 2 * scene_index as u16 >= height { break @@ -175,11 +184,13 @@ impl Arranger { "┊".blit(buf, x, y + 1, style)?; label.blit(buf, x, y, style)?; if self.selected == ArrangerFocus::Clip(track_index, scene_index) { - fill_bg(buf, Rect { x, y, width, height: 2 }, bg) + fill_bg(buf, Rect { x: area.x, y, width: area.width, height: 2 }, bg_lo); + fill_bg(buf, Rect { x, y: area.y, width, height: area.height }, bg_lo); + fill_bg(buf, Rect { x, y, width, height: 2 }, bg_hi); } } if self.selected == ArrangerFocus::Track(track_index) { - fill_bg(buf, Rect { x, y: area.y, width, height: 1 }, bg) + fill_bg(buf, Rect { x, y: area.y, width, height: 1 }, bg_hi) } x = x + width as u16; } @@ -524,11 +535,18 @@ impl ArrangerFocus { } pub fn track_prev (&mut self) { *self = match self { - Self::Mix => Self::Mix, - Self::Scene(s) => Self::Scene(*s), - Self::Track(0) => Self::Mix, - Self::Track(t) => Self::Track(*t - 1), - Self::Clip(t, s) => Self::Clip(t.saturating_sub(1), *s), + Self::Mix => Self::Mix, + Self::Scene(s) => Self::Scene(*s), + Self::Track(t) => if *t == 0 { + Self::Mix + } else { + Self::Track(*t - 1) + }, + Self::Clip(t, s) => if *t == 0 { + Self::Scene(*s) + } else { + Self::Clip(t.saturating_sub(1), *s) + } } } } @@ -545,18 +563,25 @@ impl ArrangerFocus { pub fn scene_next (&mut self, last_scene: usize) { *self = match self { Self::Mix => Self::Scene(0), - Self::Track(t) => Self::Scene(*t), + Self::Track(t) => Self::Clip(*t, 0), Self::Scene(s) => Self::Scene(last_scene.min(*s + 1)), Self::Clip(t, s) => Self::Clip(*t, last_scene.min(*s + 1)), } } pub fn scene_prev (&mut self) { *self = match self { - Self::Mix => Self::Mix, - Self::Track(t) => Self::Track(*t), - Self::Scene(0) => Self::Mix, - Self::Scene(s) => Self::Scene(*s - 1), - Self::Clip(t, s) => Self::Clip(*t, s.saturating_sub(1)), + Self::Mix => Self::Mix, + Self::Track(t) => Self::Track(*t), + Self::Scene(s) => if *s == 0 { + Self::Mix + } else { + Self::Scene(*s - 1) + }, + Self::Clip(t, s) => if *s == 0 { + Self::Track(*t) + } else { + Self::Clip(*t, s.saturating_sub(1)) + } } } } diff --git a/src/view/chain.rs b/src/view/chain.rs index 0484244c..9ca84103 100644 --- a/src/view/chain.rs +++ b/src/view/chain.rs @@ -32,15 +32,15 @@ impl<'a> Render for ChainView<'a> { Direction::Right => area.width = area.width.min(10), } fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered)); - let area = self.direction + let (area, areas) = self.direction .split_focus(0, track.devices.as_slice(), if self.focused { Style::default().green().dim() } else { Style::default().dim() }) - .render(buf, area)?; + .render_areas(buf, area)?; if self.focused && self.entered { - Corners(Style::default().green().not_dim()).draw(buf, area)?; + Corners(Style::default().green().not_dim()).draw(buf, areas[0])?; } Ok(area) } else { diff --git a/src/view/split.rs b/src/view/split.rs index 2d1eeb6b..fa318923 100644 --- a/src/view/split.rs +++ b/src/view/split.rs @@ -51,11 +51,9 @@ impl<'a, const N: usize> Split<'a, N> { pub fn right (items: [&'a (dyn Render + Sync);N]) -> Self { Self(Direction::Right, items) } -} - -impl<'a, const N: usize> Render for Split<'a, N> { - fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { + pub fn render_areas (&self, buf: &mut Buffer, area: Rect) -> Usually<(Rect, Vec)> { 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 @@ -70,9 +68,16 @@ impl<'a, const N: usize> Render for Split<'a, N> { x = x + result.width; width = width.saturating_sub(result.width); }, - } + }; + areas.push(area); } - Ok(area) + Ok((area, areas)) + } +} + +impl<'a, const N: usize> Render for Split<'a, N> { + fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { + Ok(self.render_areas(buf, area)?.0) } } @@ -80,16 +85,16 @@ type Renderables<'a> = &'a [JackDevice]; pub struct SplitFocus<'a>(pub Direction, pub usize, pub Renderables<'a>, pub Style); -impl<'a> Render for SplitFocus<'a> { - fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { +impl<'a> SplitFocus<'a> { + pub fn render_areas (&self, buf: &mut Buffer, area: Rect) -> Usually<(Rect, Vec)> { let Rect { mut x, mut y, mut width, mut height } = area; - let mut results = vec![]; + let mut areas = vec![]; for item in self.2.iter() { if width == 0 || height == 0 { break } let result = item.render(buf, Rect { x, y, width, height })?; - results.push(result); + areas.push(result); match self.0 { Direction::Down => { y = y + result.height; @@ -100,11 +105,14 @@ impl<'a> Render for SplitFocus<'a> { width = width.saturating_sub(result.width); }, } + Lozenge(self.3).draw(buf, result)?; } - results - .get(self.1) - .map(|focused|Lozenge(self.3).draw(buf, Rect { width, ..*focused })) - .transpose()?; - Ok(area) + Ok((area, areas)) + } +} + +impl<'a> Render for SplitFocus<'a> { + fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { + Ok(self.render_areas(buf, area)?.0) } } diff --git a/src/view/table.rs b/src/view/table.rs deleted file mode 100644 index dd0bd284..00000000 --- a/src/view/table.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::core::*; - -pub struct Cell { - text: String, - style: Option