mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
improve arranger navigation and higlighting
This commit is contained in:
parent
0dec568fe4
commit
d02dbe5f3b
5 changed files with 76 additions and 67 deletions
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue