mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +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> {
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue