mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: arranger: colors
This commit is contained in:
parent
70b1ec5a02
commit
08327d2ec0
5 changed files with 120 additions and 99 deletions
|
|
@ -1,6 +1,13 @@
|
|||
use crate::*;
|
||||
use ratatui::style::Modifier;
|
||||
|
||||
pub const COLOR_BG0: Color = Color::Rgb(30, 33, 36);
|
||||
pub const COLOR_BG1: Color = Color::Rgb(41, 46, 57);
|
||||
pub const COLOR_BG2: Color = Color::Rgb(46, 52, 64);
|
||||
pub const COLOR_BG3: Color = Color::Rgb(59, 66, 82);
|
||||
pub const COLOR_BG4: Color = Color::Rgb(67, 76, 94);
|
||||
pub const COLOR_BG5: Color = Color::Rgb(76, 86, 106);
|
||||
|
||||
pub trait Theme {
|
||||
const BG0: Color;
|
||||
const BG1: Color;
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ handle!(Arranger |self, e| {
|
|||
|
||||
/// Key bindings for arranger section.
|
||||
pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
||||
[Char('`'), NONE, "arranger_mode_switch", "switch the display mode", |arranger: &mut Arranger| {
|
||||
[Char('`'), NONE, "mode_switch", "switch the display mode", |arranger: &mut Arranger| {
|
||||
arranger.mode.to_next();
|
||||
Ok(true)
|
||||
}],
|
||||
[Up, NONE, "arranger_cursor_up", "move cursor up", |arranger: &mut Arranger| {
|
||||
[Up, NONE, "cursor_up", "move cursor up", |arranger: &mut Arranger| {
|
||||
match arranger.mode {
|
||||
ArrangerViewMode::Horizontal => arranger.track_prev(),
|
||||
_ => arranger.scene_prev(),
|
||||
|
|
@ -27,7 +27,7 @@ pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
|||
arranger.show_phrase()?;
|
||||
Ok(true)
|
||||
}],
|
||||
[Down, NONE, "arranger_cursor_down", "move cursor down", |arranger: &mut Arranger| {
|
||||
[Down, NONE, "cursor_down", "move cursor down", |arranger: &mut Arranger| {
|
||||
match arranger.mode {
|
||||
ArrangerViewMode::Horizontal => arranger.track_next(),
|
||||
_ => arranger.scene_next(),
|
||||
|
|
@ -35,7 +35,7 @@ pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
|||
arranger.show_phrase()?;
|
||||
Ok(true)
|
||||
}],
|
||||
[Left, NONE, "arranger_cursor_left", "move cursor left", |arranger: &mut Arranger| {
|
||||
[Left, NONE, "cursor_left", "move cursor left", |arranger: &mut Arranger| {
|
||||
match arranger.mode {
|
||||
ArrangerViewMode::Horizontal => arranger.scene_prev(),
|
||||
_ => arranger.track_prev(),
|
||||
|
|
@ -43,7 +43,7 @@ pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
|||
arranger.show_phrase()?;
|
||||
Ok(true)
|
||||
}],
|
||||
[Right, NONE, "arranger_cursor_right", "move cursor right", |arranger: &mut Arranger| {
|
||||
[Right, NONE, "cursor_right", "move cursor right", |arranger: &mut Arranger| {
|
||||
match arranger.mode {
|
||||
ArrangerViewMode::Horizontal => arranger.scene_next(),
|
||||
_ => arranger.track_next(),
|
||||
|
|
@ -51,15 +51,15 @@ pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
|||
arranger.show_phrase()?;
|
||||
Ok(true)
|
||||
}],
|
||||
[Char('.'), NONE, "arranger_increment", "set next clip at cursor", |arranger: &mut Arranger| {
|
||||
[Char('.'), NONE, "increment", "set next clip at cursor", |arranger: &mut Arranger| {
|
||||
arranger.phrase_next();
|
||||
Ok(true)
|
||||
}],
|
||||
[Char(','), NONE, "arranger_decrement", "set previous clip at cursor", |arranger: &mut Arranger| {
|
||||
[Char(','), NONE, "decrement", "set previous clip at cursor", |arranger: &mut Arranger| {
|
||||
arranger.phrase_prev();
|
||||
Ok(true)
|
||||
}],
|
||||
[Enter, NONE, "arranger_activate", "activate item at cursor", |arranger: &mut Arranger| {
|
||||
[Enter, NONE, "activate", "activate item at cursor", |arranger: &mut Arranger| {
|
||||
arranger.activate();
|
||||
Ok(true)
|
||||
}],
|
||||
|
|
@ -78,5 +78,9 @@ pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
|||
[Char('l'), NONE, "length", "set length of item at cursor", |arranger: &mut Arranger| {
|
||||
todo!();
|
||||
Ok(true)
|
||||
}],
|
||||
[Char('c'), NONE, "color", "set color of item at cursor", |arranger: &mut Arranger| {
|
||||
todo!();
|
||||
Ok(true)
|
||||
}]
|
||||
});
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ impl ArrangerStandalone {
|
|||
}
|
||||
for _ in 0..args.scenes {
|
||||
let scene = app.arranger.scene_add(None)?;
|
||||
for i in 0..args.tracks {
|
||||
scene.clips[i] = Some(i);
|
||||
}
|
||||
}
|
||||
Ok(app)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ pub fn draw (
|
|||
let tracks = state.tracks.as_ref();
|
||||
let scenes = state.scenes.as_ref();
|
||||
Layered::new()
|
||||
.add(FillBg(Nord::bg_lo(state.focused, state.entered)))
|
||||
.add(ColumnSeparators(offset, cols))
|
||||
.add(CursorFocus(focus_sequencer, focused, entered, selected, offset, cols, rows))
|
||||
.add(Split::down()
|
||||
.add(TracksHeader(offset, cols, tracks))
|
||||
.add(SceneRows(offset, cols, rows, tracks, scenes)))
|
||||
.add(RowSeparators(rows))
|
||||
//.add_ref(&FillBg(Color::Rgb(30, 33, 36)))//COLOR_BG1))//bg_lo(state.focused, state.entered)))
|
||||
.add_ref(&ColumnSeparators(offset, cols))
|
||||
.add_ref(&Split::down()
|
||||
.add_ref(&TracksHeader(offset, cols, tracks))
|
||||
.add_ref(&SceneRows(offset, cols, rows, tracks, scenes)))
|
||||
.add_ref(&CursorFocus(focus_sequencer, focused, entered, selected, offset, cols, rows))
|
||||
.add_ref(&RowSeparators(rows))
|
||||
.render(buf, area)
|
||||
}
|
||||
|
||||
|
|
@ -87,60 +87,43 @@ struct CursorFocus<'a>(
|
|||
impl<'a> Render for CursorFocus<'a> {
|
||||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
let Self(focus_sequencer, focused, entered, selected, offset, cols, rows) = *self;
|
||||
let track_area = |t: usize| Rect {
|
||||
x: offset + area.x + cols[t].1 as u16 - 1,
|
||||
y: area.y,
|
||||
width: cols[t].0 as u16,
|
||||
height: area.height
|
||||
};
|
||||
let scene_area = |s: usize| Rect {
|
||||
x: area.x,
|
||||
y: 2 + area.y + (rows[s].1 / 96) as u16,
|
||||
width: area.width,
|
||||
height: (rows[s].0 / 96) as u16
|
||||
};
|
||||
let clip_area = |t: usize, s: usize| Rect {
|
||||
x: offset + area.x + cols[t].1 as u16 - 1,
|
||||
y: 2 + area.y + (rows[s].1 / 96) as u16,
|
||||
width: cols[t].0 as u16,
|
||||
height: (rows[s].0 / 96) as u16
|
||||
};
|
||||
let area = match selected {
|
||||
ArrangerFocus::Mix => if focused
|
||||
&& entered
|
||||
&& selected == ArrangerFocus::Mix
|
||||
{
|
||||
fill_bg(buf, area, Nord::bg_hi(focused, entered));
|
||||
ArrangerFocus::Mix => if focused && entered && selected == ArrangerFocus::Mix {
|
||||
fill_bg(buf, area, COLOR_BG3);
|
||||
area
|
||||
} else {
|
||||
area
|
||||
},
|
||||
ArrangerFocus::Track(t) => {
|
||||
let area = Rect {
|
||||
x: offset + area.x + cols[t].1 as u16 - 1,
|
||||
y: area.y,
|
||||
width: cols[t].0 as u16,
|
||||
height: area.height
|
||||
};
|
||||
fill_bg(buf, area, Nord::bg_hi(focused, entered));
|
||||
fill_bg(buf, track_area(t), COLOR_BG3);
|
||||
area
|
||||
},
|
||||
ArrangerFocus::Scene(s) => {
|
||||
let area = Rect {
|
||||
x: area.x,
|
||||
y: 2 + area.y + (rows[s].1 / 96) as u16,
|
||||
width: area.width,
|
||||
height: (rows[s].0 / 96) as u16
|
||||
};
|
||||
fill_bg(buf, area, Nord::bg_hi(focused, entered));
|
||||
fill_bg(buf, scene_area(s), COLOR_BG3);
|
||||
area
|
||||
},
|
||||
ArrangerFocus::Clip(t, s) => {
|
||||
let track_area = Rect {
|
||||
x: offset + area.x + cols[t].1 as u16 - 1,
|
||||
y: area.y,
|
||||
width: cols[t].0 as u16,
|
||||
height: area.height
|
||||
};
|
||||
let scene_area = Rect {
|
||||
x: area.x,
|
||||
y: 2 + area.y + (rows[s].1 / 96) as u16,
|
||||
width: area.width,
|
||||
height: (rows[s].0 / 96) as u16
|
||||
};
|
||||
let area = Rect {
|
||||
x: offset + area.x + cols[t].1 as u16 - 1,
|
||||
y: 2 + area.y + (rows[s].1 / 96) as u16,
|
||||
width: cols[t].0 as u16,
|
||||
height: (rows[s].0 / 96) as u16
|
||||
};
|
||||
let lo = Nord::bg_hi(focused, entered);
|
||||
let hi = Nord::bg_hier(focused, entered);
|
||||
fill_bg(buf, track_area, lo);
|
||||
fill_bg(buf, scene_area, lo);
|
||||
fill_bg(buf, area, hi);
|
||||
fill_bg(buf, track_area(t), COLOR_BG2);
|
||||
fill_bg(buf, scene_area(s), COLOR_BG2);
|
||||
fill_bg(buf, clip_area(t, s), COLOR_BG3);
|
||||
area
|
||||
},
|
||||
};
|
||||
|
|
@ -157,12 +140,14 @@ impl<'a> Render for TracksHeader<'a> {
|
|||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
let Self(offset, track_cols, tracks) = *self;
|
||||
let Rect { y, width, .. } = area;
|
||||
for (track, (_, x)) in tracks.iter().zip(track_cols) {
|
||||
for (track, (w, x)) in tracks.iter().zip(track_cols) {
|
||||
let x = *x as u16;
|
||||
if x > width {
|
||||
break
|
||||
}
|
||||
track.name.read().unwrap().blit(buf, offset + x + 1, y, Some(Style::default()))?;
|
||||
let name = track.name.read().unwrap();
|
||||
fill_bg(buf, Rect { x: offset + x, y, width: *w as u16, height: 2 }, COLOR_BG1);
|
||||
name.blit(buf, offset + x + 1, y, Some(Style::default().white()))?;
|
||||
}
|
||||
Ok(Rect { x: area.x, y, width, height: 2 })
|
||||
}
|
||||
|
|
@ -184,56 +169,69 @@ impl<'a> Render for SceneRows<'a> {
|
|||
}
|
||||
}
|
||||
for (scene, (pulses, _)) in scenes.iter().zip(scene_rows) {
|
||||
if y > height {
|
||||
break
|
||||
}
|
||||
//if y > height {
|
||||
//break
|
||||
//}
|
||||
let h = 1.max((pulses / 96) as u16);
|
||||
scene_row(tracks, buf, Rect {
|
||||
SceneRow(tracks, scene, track_cols, offset).render(buf, Rect {
|
||||
x: area.x,
|
||||
y,
|
||||
width: area.width,
|
||||
height: h,//.min(area.height - y)
|
||||
}, scene, track_cols, offset)?;
|
||||
})?;
|
||||
y = y + h
|
||||
}
|
||||
Ok(area)
|
||||
}
|
||||
}
|
||||
|
||||
fn scene_row <'a> (
|
||||
tracks: &'a[Sequencer],
|
||||
buf: &mut Buffer,
|
||||
area: Rect,
|
||||
scene: &Scene,
|
||||
track_cols: &[(usize, usize)],
|
||||
offset: u16
|
||||
) -> Usually<u16> {
|
||||
let Rect { y, width, .. } = area;
|
||||
let playing = scene.is_playing(tracks);
|
||||
(if playing { "▶" } else { " " }).blit(buf, area.x, y, None)?;
|
||||
scene.name.read().unwrap().blit(buf, area.x + 1, y, None)?;
|
||||
let style = Some(Style::default().white());
|
||||
for (track, (w, x)) in track_cols.iter().enumerate() {
|
||||
let x = *x as u16 + offset;
|
||||
if x > width {
|
||||
break
|
||||
}
|
||||
if let (Some(track), Some(Some(clip))) = (
|
||||
tracks.get(track), scene.clips.get(track)
|
||||
) {
|
||||
if let Some(phrase) = track.phrases.get(*clip) {
|
||||
let phrase = phrase.read().unwrap();
|
||||
phrase.name.read().unwrap().blit(buf, x + 1, y, style)?;
|
||||
if track.sequence == Some(*clip) {
|
||||
fill_bg(buf, Rect {
|
||||
x: x - 1,
|
||||
y,
|
||||
width: *w as u16,
|
||||
height: area.height,
|
||||
}, Nord::PLAYING);
|
||||
}
|
||||
struct SceneRow<'a>(&'a[Sequencer], &'a Scene, &'a[(usize, usize)], u16);
|
||||
|
||||
impl<'a> Render for SceneRow<'a> {
|
||||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
let Self(tracks, scene, track_cols, offset) = self;
|
||||
let Rect { x, y, width, .. } = area;
|
||||
let playing = scene.is_playing(tracks);
|
||||
(if playing { "▶" } else { " " }).blit(buf, x, y, None)?;
|
||||
scene.name.read().unwrap().blit(buf, x + 1, y, Some(Style::default().white()))?;
|
||||
fill_bg(buf, Rect { x: x, y, width: offset.saturating_sub(1), height: 2 }, COLOR_BG1);
|
||||
|
||||
for (track, (w, x)) in track_cols.iter().enumerate() {
|
||||
let x = *x as u16 + offset;
|
||||
if x > width {
|
||||
break
|
||||
}
|
||||
|
||||
if let (Some(track), Some(Some(clip))) = (
|
||||
tracks.get(track), scene.clips.get(track)
|
||||
) {
|
||||
let area = Rect { x, y, width: *w as u16, height: area.height, };
|
||||
SceneClip(track, *clip).render(buf, area)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(area)
|
||||
}
|
||||
}
|
||||
|
||||
struct SceneClip<'a>(&'a Sequencer, usize);
|
||||
|
||||
impl<'a> Render for SceneClip<'a> {
|
||||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
let Self(track, clip) = self;
|
||||
let style = Some(Style::default().white());
|
||||
if let Some(phrase) = track.phrases.get(*clip) {
|
||||
let phrase = phrase.read().unwrap();
|
||||
let name = phrase.name.read().unwrap();
|
||||
name.blit(buf, area.x + 1, area.y, style)?;
|
||||
fill_bg(buf, area, if track.sequence == Some(*clip) {
|
||||
Nord::PLAYING
|
||||
} else {
|
||||
COLOR_BG1
|
||||
});
|
||||
} else {
|
||||
fill_bg(buf, area, COLOR_BG0)
|
||||
}
|
||||
Ok(area)
|
||||
}
|
||||
Ok((scene.pulses(tracks) / 96) as u16)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,13 @@ impl Scene {
|
|||
/// Returns the pulse length of the longest phrase in the scene
|
||||
pub fn pulses (&self, tracks: &[Sequencer]) -> usize {
|
||||
self.clips.iter().enumerate()
|
||||
.filter_map(|(i, c)|c.map(|c|tracks[i].phrases.get(c)))
|
||||
.filter_map(|(i, c)|c
|
||||
.map(|c|tracks
|
||||
.get(i)
|
||||
.map(|track|track
|
||||
.phrases
|
||||
.get(c))))
|
||||
.filter_map(|p|p)
|
||||
.filter_map(|p|p)
|
||||
.fold(0, |a, p|a.max(p.read().unwrap().length))
|
||||
}
|
||||
|
|
@ -47,7 +53,10 @@ impl Scene {
|
|||
pub fn is_playing (&self, tracks: &[Sequencer]) -> bool {
|
||||
self.clips.iter().enumerate()
|
||||
.all(|(track_index, phrase_index)|match phrase_index {
|
||||
Some(i) => tracks[track_index].sequence == Some(*i),
|
||||
Some(i) => tracks
|
||||
.get(track_index)
|
||||
.map(|track|track.sequence == Some(*i))
|
||||
.unwrap_or(false),
|
||||
None => true
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue