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> {
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))
}
}
}
}

View file

@ -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 {

View file

@ -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<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 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<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);
impl<'a> Render for SplitFocus<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
impl<'a> SplitFocus<'a> {
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 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<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 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 {
if focused && entered {
Self::BG2