improve arranger navigation and higlighting

This commit is contained in:
🪞👃🪞 2024-07-14 00:29:46 +03:00
parent 0dec568fe4
commit d02dbe5f3b
5 changed files with 76 additions and 67 deletions

View file

@ -120,12 +120,14 @@ impl Arranger {
} }
fn draw_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn draw_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let bg_hi = Nord::bg_hier(self.focused, self.entered);
let bg_lo = Nord::bg_hi(self.focused, self.entered);
return Split::right([ return Split::right([
// Scene column // Scene column
&|buf: &mut Buffer, area: Rect|{ &|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() { for (scene_index, scene) in self.scenes.iter().enumerate() {
if y + 2 * scene_index as u16 >= height { if y + 2 * scene_index as u16 >= height {
break break
@ -140,6 +142,14 @@ impl Arranger {
}); });
if playing { "" } else { " " }.blit(buf, x+1, y, style)?; if playing { "" } else { " " }.blit(buf, x+1, y, style)?;
scene.name.blit(buf, x + 2, 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() let width = 2 + self.scenes.iter()
.map(|x|&x.name).fold(0, |x,y|x.max(y.len() as u16+1)); .map(|x|&x.name).fold(0, |x,y|x.max(y.len() as u16+1));
@ -155,7 +165,6 @@ impl Arranger {
} }
let width = 16u16; let width = 16u16;
track.name.blit(buf, x, y, Some(Style::default().bold()))?; 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() { for (scene_index, scene) in self.scenes.iter().enumerate() {
if y + 2 * scene_index as u16 >= height { if y + 2 * scene_index as u16 >= height {
break break
@ -175,11 +184,13 @@ impl Arranger {
"".blit(buf, x, y + 1, style)?; "".blit(buf, x, y + 1, style)?;
label.blit(buf, x, y, style)?; label.blit(buf, x, y, style)?;
if self.selected == ArrangerFocus::Clip(track_index, scene_index) { 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) { 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; x = x + width as u16;
} }
@ -524,11 +535,18 @@ impl ArrangerFocus {
} }
pub fn track_prev (&mut self) { pub fn track_prev (&mut self) {
*self = match self { *self = match self {
Self::Mix => Self::Mix, Self::Mix => Self::Mix,
Self::Scene(s) => Self::Scene(*s), Self::Scene(s) => Self::Scene(*s),
Self::Track(0) => Self::Mix, Self::Track(t) => if *t == 0 {
Self::Track(t) => Self::Track(*t - 1), Self::Mix
Self::Clip(t, s) => Self::Clip(t.saturating_sub(1), *s), } 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) { pub fn scene_next (&mut self, last_scene: usize) {
*self = match self { *self = match self {
Self::Mix => Self::Scene(0), 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::Scene(s) => Self::Scene(last_scene.min(*s + 1)),
Self::Clip(t, s) => Self::Clip(*t, last_scene.min(*s + 1)), Self::Clip(t, s) => Self::Clip(*t, last_scene.min(*s + 1)),
} }
} }
pub fn scene_prev (&mut self) { pub fn scene_prev (&mut self) {
*self = match self { *self = match self {
Self::Mix => Self::Mix, Self::Mix => Self::Mix,
Self::Track(t) => Self::Track(*t), Self::Track(t) => Self::Track(*t),
Self::Scene(0) => Self::Mix, Self::Scene(s) => if *s == 0 {
Self::Scene(s) => Self::Scene(*s - 1), Self::Mix
Self::Clip(t, s) => Self::Clip(*t, s.saturating_sub(1)), } else {
Self::Scene(*s - 1)
},
Self::Clip(t, s) => if *s == 0 {
Self::Track(*t)
} else {
Self::Clip(*t, s.saturating_sub(1))
}
} }
} }
} }

View file

@ -32,15 +32,15 @@ impl<'a> Render for ChainView<'a> {
Direction::Right => area.width = area.width.min(10), Direction::Right => area.width = area.width.min(10),
} }
fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered)); 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 { .split_focus(0, track.devices.as_slice(), if self.focused {
Style::default().green().dim() Style::default().green().dim()
} else { } else {
Style::default().dim() Style::default().dim()
}) })
.render(buf, area)?; .render_areas(buf, area)?;
if self.focused && self.entered { 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) Ok(area)
} else { } else {

View file

@ -51,11 +51,9 @@ impl<'a, const N: usize> Split<'a, N> {
pub fn right (items: [&'a (dyn Render + Sync);N]) -> Self { pub fn right (items: [&'a (dyn Render + Sync);N]) -> Self {
Self(Direction::Right, items) Self(Direction::Right, items)
} }
} pub fn render_areas (&self, buf: &mut Buffer, area: Rect) -> Usually<(Rect, Vec<Rect>)> {
impl<'a, const N: usize> Render for Split<'a, N> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let Rect { mut x, mut y, mut width, mut height } = area; let Rect { mut x, mut y, mut width, mut height } = area;
let mut areas = vec![];
for item in self.1 { for item in self.1 {
if width == 0 || height == 0 { if width == 0 || height == 0 {
break break
@ -70,9 +68,16 @@ impl<'a, const N: usize> Render for Split<'a, N> {
x = x + result.width; x = x + result.width;
width = width.saturating_sub(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<Rect> {
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); pub struct SplitFocus<'a>(pub Direction, pub usize, pub Renderables<'a>, pub Style);
impl<'a> Render for SplitFocus<'a> { impl<'a> SplitFocus<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> { 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 Rect { mut x, mut y, mut width, mut height } = area;
let mut results = vec![]; let mut areas = vec![];
for item in self.2.iter() { for item in self.2.iter() {
if width == 0 || height == 0 { if width == 0 || height == 0 {
break break
} }
let result = item.render(buf, Rect { x, y, width, height })?; let result = item.render(buf, Rect { x, y, width, height })?;
results.push(result); areas.push(result);
match self.0 { match self.0 {
Direction::Down => { Direction::Down => {
y = y + result.height; y = y + result.height;
@ -100,11 +105,14 @@ impl<'a> Render for SplitFocus<'a> {
width = width.saturating_sub(result.width); width = width.saturating_sub(result.width);
}, },
} }
Lozenge(self.3).draw(buf, result)?;
} }
results Ok((area, areas))
.get(self.1) }
.map(|focused|Lozenge(self.3).draw(buf, Rect { width, ..*focused })) }
.transpose()?;
Ok(area) impl<'a> Render for SplitFocus<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
Ok(self.render_areas(buf, area)?.0)
} }
} }

View file

@ -1,34 +0,0 @@
use crate::core::*;
pub struct Cell<T> {
text: String,
style: Option<Style>,
width: u16,
height: u16,
data: T
}
impl<T> Cell<T> {
pub fn new (text: &str, data: T) -> Self {
Self { text: text.to_string(), style: None, width: text.len() as u16, height: 1, data }
}
pub fn draw (&self, buf: &mut Buffer, x: u16, y: u16) {
self.text.blit(buf, x, y, self.style)
}
}
pub struct Table<T> {
columns: Vec<Vec<Cell<T>>>,
row: usize,
col: usize,
}
impl<T> Table<T> {
pub fn new (columns: Vec<Vec<Cell<T>>>) -> Self {
Self { columns, row: 0, col: 0 }
}
pub fn set (&mut self, col: usize, row: usize, cell: Cell<T>) {
self.columns[col][row] = cell;
}
}

View file

@ -10,6 +10,16 @@ pub trait Theme {
const YELLOW: Color; const YELLOW: Color;
const GREEN: Color; const GREEN: Color;
fn bg_hier (focused: bool, entered: bool) -> Color {
if focused && entered {
Self::BG3
} else if focused {
Self::BG2
} else {
Self::BG1
}
}
fn bg_hi (focused: bool, entered: bool) -> Color { fn bg_hi (focused: bool, entered: bool) -> Color {
if focused && entered { if focused && entered {
Self::BG2 Self::BG2