Compare commits

..

No commits in common. "a67481ab044e5abbfef81575a64ad707ecde28c6" and "b4761a9679d9e16c8d786eed2fe07d16d4316aa8" have entirely different histories.

View file

@ -23,8 +23,8 @@ impl Tek {
pub fn view_modal (&self) -> impl Content<TuiOut> + use<'_> { pub fn view_modal (&self) -> impl Content<TuiOut> + use<'_> {
When::new(self.modal.is_some(), Bsp::b( When::new(self.modal.is_some(), Bsp::b(
Fill::xy(Tui::fg_bg(Rgb(64,64,64), Rgb(32,32,32), "")), Fill::xy(Tui::fg_bg(Color::Rgb(64,64,64), Color::Rgb(32,32,32), "")),
Fixed::xy(30, 15, Tui::fg_bg(Rgb(255,255,255), Rgb(16,16,16), Bsp::b( Fixed::xy(30, 15, Tui::fg_bg(Color::Rgb(255,255,255), Color::Rgb(16,16,16), Bsp::b(
Repeat(" "), Repeat(" "),
Outer(true, Style::default().fg(Tui::g(96))) Outer(true, Style::default().fg(Tui::g(96)))
.enclose(self.modal.map(|modal|match modal { .enclose(self.modal.map(|modal|match modal {
@ -37,7 +37,7 @@ impl Tek {
fn view_modal_menu (&self) -> impl Content<TuiOut> { fn view_modal_menu (&self) -> impl Content<TuiOut> {
let options = ||["Projects", "Settings", "Help", "Quit"].iter(); let options = ||["Projects", "Settings", "Help", "Quit"].iter();
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a)); let option = |a,i|Tui::fg(Color::Rgb(255,255,255), format!("{}", a));
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option))) Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
} }
@ -51,14 +51,14 @@ impl Tek {
None None
}); });
let binding = |mut binding: TokenIter, _|Bsp::e( let binding = |mut binding: TokenIter, _|Bsp::e(
Fixed::x(15, Align::w(Tui::bold(true, Tui::fg(Rgb(255,192,0), if let Some(Token { Fixed::x(15, Align::w(Tui::bold(true, Tui::fg(Color::Rgb(255,192,0), if let Some(Token {
value: Value::Sym(key), .. value: Value::Sym(key), ..
}) = binding.next() { }) = binding.next() {
Some(key.to_string()) Some(key.to_string())
} else { } else {
None None
})))), })))),
Bsp::e(" ", Tui::fg(Rgb(255,255,255), if let Some(Token { Bsp::e(" ", Tui::fg(Color::Rgb(255,255,255), if let Some(Token {
value: Value::Key(command), .. value: Value::Key(command), ..
}) = binding.next() { }) = binding.next() {
Some(command.to_string()) Some(command.to_string())
@ -134,35 +134,24 @@ impl Tek {
/// Height available to display track headers. /// Height available to display track headers.
pub(crate) fn h_tracks_area (&self) -> u16 { pub(crate) fn h_tracks_area (&self) -> u16 {
5 // FIXME 5
//self.h().saturating_sub(self.h_inputs() + self.h_outputs()) //self.h().saturating_sub(self.h_inputs() + self.h_outputs())
} }
/// Height available to display tracks. /// Height available to display tracks.
pub(crate) fn h_scenes_area (&self) -> u16 { pub(crate) fn h_scenes_area (&self) -> u16 {
//15 //15
self.h().saturating_sub( self.h().saturating_sub(self.h_inputs() + self.h_outputs() + 11)
self.h_inputs() +
self.h_outputs() +
self.h_devices() +
13 // FIXME
)
} }
/// Height taken by all inputs. /// Height taken by all inputs.
pub(crate) fn h_inputs (&self) -> u16 { pub(crate) fn h_inputs (&self) -> u16 {
self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0) 1 + self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
} }
/// Height taken by all outputs. /// Height taken by all outputs.
pub(crate) fn h_outputs (&self) -> u16 { pub(crate) fn h_outputs (&self) -> u16 {
self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0) 1 + self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by visible device slots.
pub(crate) fn h_devices (&self) -> u16 {
2
//1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
} }
/// Height taken by all scenes. /// Height taken by all scenes.
@ -266,14 +255,13 @@ pub(crate) struct ArrangerView<'a> {
impl<'a> Content<TuiOut> for ArrangerView<'a> { impl<'a> Content<TuiOut> for ArrangerView<'a> {
fn content (&self) -> impl Render<TuiOut> { fn content (&self) -> impl Render<TuiOut> {
let ins = |x|Bsp::n(self.inputs(), x); let ins = |x|Bsp::s(self.inputs(), x);
let tracks = |x|Bsp::s(self.tracks(), x); let tracks = |x|Bsp::s(self.tracks(), x);
let devices = |x|Bsp::s(self.devices(), x); let outs = |x|Bsp::n(self.outputs(), x);
let outs = |x|Bsp::s(self.outputs(), x); let bg = |x|Tui::bg(Color::Reset, x);
let bg = |x|Tui::bg(Reset, x);
//let track_scroll = |x|Bsp::s(&self.track_scroll, x); //let track_scroll = |x|Bsp::s(&self.track_scroll, x);
//let scene_scroll = |x|Bsp::e(&self.scene_scroll, x); //let scene_scroll = |x|Bsp::e(&self.scene_scroll, x);
outs(tracks(devices(ins(bg(self.scenes()))))) ins(tracks(outs(bg(self.scenes()))))
} }
} }
@ -287,10 +275,10 @@ impl<'a> ArrangerView<'a> {
width_mid: app.w_tracks_area(), width_mid: app.w_tracks_area(),
width_side: app.w_sidebar(), width_side: app.w_sidebar(),
inputs_height: app.h_inputs(), inputs_height: app.h_inputs().saturating_sub(1),
inputs_count: app.midi_ins.len(), inputs_count: app.midi_ins.len(),
outputs_height: app.h_outputs(), outputs_height: app.h_outputs().saturating_sub(1),
outputs_count: app.midi_outs.len(), outputs_count: app.midi_outs.len(),
scenes_height: app.h_scenes_area(), scenes_height: app.h_scenes_area(),
@ -318,57 +306,12 @@ impl<'a> ArrangerView<'a> {
/// Render input matrix. /// Render input matrix.
pub(crate) fn inputs (&'a self) -> impl Content<TuiOut> + 'a { pub(crate) fn inputs (&'a self) -> impl Content<TuiOut> + 'a {
Tui::bg(Reset, Bsp::s( Tui::bg(Color::Reset, Bsp::s(
self.input_intos(),
Bsp::s(self.input_routes(), self.input_ports()), Bsp::s(self.input_routes(), self.input_ports()),
self.input_intos()
)) ))
} }
/// Render output matrix.
pub(crate) fn outputs (&'a self) -> impl Content<TuiOut> + 'a {
Tui::bg(Reset, Align::n(Bsp::s(
Bsp::s(self.output_ports(), self.output_conns()),
Bsp::s(self.output_nexts(), self.output_froms()),
)))
}
/// Render device switches.
pub(crate) fn devices (&'a self) -> impl Content<TuiOut> + 'a {
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
Tryptich::top(1)
.left(*width_side, button_3("x", "devices", format!("{}", 0), *is_editing))
.right(*width_side, button_2("X", "add device", *is_editing))
.middle(*width_mid, per_track_top(*width_mid, ||self.tracks_with_sizes_scrolled(),
move|index, track|{
wrap(if *track_selected == Some(index) {
track.color.light
} else {
track.color.base
}.rgb, Tui::g(224), Tui::bold(true, Fill::x(Bsp::e(
Tui::fg_bg(Reset, Reset, "[ "),
Tui::fg_bg(Reset, Reset, " ]"),
))))
}))
}
/// Render track headers
pub(crate) fn tracks (&'a self) -> impl Content<TuiOut> + 'a {
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
Tryptich::center(3)
.left(*width_side, button_3("t", "track", format!("{}", *track_count), *is_editing))
.right(*width_side, button_2("T", "add track", *is_editing))
.middle(*width_mid, per_track(*width_mid, ||self.tracks_with_sizes_scrolled(),
|index, track|wrap(
if *track_selected == Some(index) {
track.color.light
} else {
track.color.base
}.rgb,
track.color.lightest.rgb,
Tui::bold(true, Fill::xy(Align::nw(&track.name)))
)))
}
fn input_routes (&'a self) -> impl Content<TuiOut> + 'a { fn input_routes (&'a self) -> impl Content<TuiOut> + 'a {
Tryptich::top(self.inputs_height) Tryptich::top(self.inputs_height)
.left(self.width_side, .left(self.width_side,
@ -421,6 +364,14 @@ impl<'a> ArrangerView<'a> {
|_, _|Tui::bg(Reset, Align::c(Bsp::s(OctaveVertical::default(), " ------ "))))) |_, _|Tui::bg(Reset, Align::c(Bsp::s(OctaveVertical::default(), " ------ ")))))
} }
/// Render output matrix.
pub(crate) fn outputs (&'a self) -> impl Content<TuiOut> + 'a {
Tui::bg(Color::Reset, Align::n(Bsp::s(
Bsp::s(self.output_nexts(), self.output_froms()),
Bsp::s(self.output_ports(), self.output_conns()),
)))
}
fn output_nexts (&'a self) -> impl Content<TuiOut> + 'a { fn output_nexts (&'a self) -> impl Content<TuiOut> + 'a {
Tryptich::top(2) Tryptich::top(2)
.left(self.width_side, Align::ne("From clip:")) .left(self.width_side, Align::ne("From clip:"))
@ -458,35 +409,58 @@ impl<'a> ArrangerView<'a> {
.right(self.width_side, .right(self.width_side,
button_2("O", "add midi out", self.is_editing)) button_2("O", "add midi out", self.is_editing))
.middle(self.width_mid, .middle(self.width_mid,
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), move|i, t|{ per_track_top(
let mute = false; self.width_mid,
let solo = false; ||self.tracks_with_sizes_scrolled(),
let mute = if mute { White } else { t.color.darkest.rgb }; move|i, t|{
let solo = if solo { White } else { t.color.darkest.rgb }; let mute = false;
let bg_1 = if self.track_selected == Some(i) { let solo = false;
t.color.light.rgb let mute = if mute { White } else { t.color.darkest.rgb };
} else { let solo = if solo { White } else { t.color.darkest.rgb };
t.color.base.rgb let bg_1 = if self.track_selected == Some(i) {
}; t.color.light.rgb
let bg_2 = if i > 0 { t.color.base.rgb } else { Reset }; } else {
let mute = Tui::fg_bg(mute, bg_1, "Play "); t.color.base.rgb
let solo = Tui::fg_bg(solo, bg_1, "Solo "); };
wrap(bg_1, Tui::g(224), Tui::bold(true, Fill::x(Bsp::e(mute, solo)))) let bg_2 = if i > 0 { t.color.base.rgb } else { Reset };
})) let mute = Tui::fg_bg(mute, bg_1, "Play ");
let solo = Tui::fg_bg(solo, bg_1, "Solo ");
wrap(bg_1, Tui::g(224), Tui::bold(true, Fill::x(Bsp::e(mute, solo))))
}))
} }
fn output_conns (&'a self) -> impl Content<TuiOut> + 'a { fn output_conns (&'a self) -> impl Content<TuiOut> + 'a {
Tryptich::top(self.outputs_height) Tryptich::top(self.outputs_height)
.left(self.width_side, .left(self.width_side,
io_ports(Tui::g(224), Tui::g(32), ||self.app.outputs_with_sizes())) io_ports(Tui::g(224), Tui::g(32), ||self.app.outputs_with_sizes()))
.middle(self.width_mid, .middle(self.width_mid, per_track_top(
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), |_, t|io_conns( self.width_mid,
||self.tracks_with_sizes_scrolled(),
|_, t|io_conns(
t.color.dark.rgb, t.color.dark.rgb,
t.color.darker.rgb, t.color.darker.rgb,
||self.app.outputs_with_sizes() ||self.app.outputs_with_sizes()
))) )))
} }
/// Render track headers
pub(crate) fn tracks (&'a self) -> impl Content<TuiOut> + 'a {
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
Tryptich::center(3)
.left(*width_side, button_3("t", "track", format!("{}", *track_count), *is_editing))
.right(*width_side, button_2("T", "add track", *is_editing))
.middle(*width_mid, per_track(*width_mid, ||self.tracks_with_sizes_scrolled(),
|index, track|wrap(
if *track_selected == Some(index) {
track.color.light
} else {
track.color.base
}.rgb,
track.color.lightest.rgb,
Tui::bold(true, Fill::x(Align::nw(&track.name)))
)))
}
/// Render scenes with clips /// Render scenes with clips
pub(crate) fn scenes (&'a self) -> impl Content<TuiOut> + 'a { pub(crate) fn scenes (&'a self) -> impl Content<TuiOut> + 'a {
@ -715,14 +689,17 @@ pub(crate) fn view_meters (values: &[f32;2]) -> impl Content<TuiOut> + use<'_> {
} }
pub(crate) fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> { pub(crate) fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
let left = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV(""))); let left = Tui::fg_bg(bg, Reset, "");
let right = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV(""))); let right = Tui::fg_bg(bg, Reset, "");
Bsp::e(left, Bsp::w(right, Tui::fg_bg(fg, bg, content))) Bsp::e(left, Bsp::w(right, Tui::fg_bg(fg, bg, content)))
} }
pub(crate) fn button_2 <'a> ( pub(crate) fn button_2 <'a, K, L> (
key: impl Content<TuiOut> + 'a, label: impl Content<TuiOut> + 'a, editing: bool, key: K, label: L, editing: bool,
) -> impl Content<TuiOut> + 'a { ) -> impl Content<TuiOut> + 'a where
K: Content<TuiOut> + 'a,
L: Content<TuiOut> + 'a,
{
let key = Tui::fg_bg(Tui::g(0), Tui::orange(), Bsp::e( let key = Tui::fg_bg(Tui::g(0), Tui::orange(), Bsp::e(
Tui::fg_bg(Tui::orange(), Reset, ""), Tui::fg_bg(Tui::orange(), Reset, ""),
Bsp::e(key, Tui::fg(Tui::g(96), "")) Bsp::e(key, Tui::fg(Tui::g(96), ""))
@ -950,7 +927,7 @@ content!(TuiOut: |self: PoolView<'a>| {
let border = |x|x;//Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb)).enclose(x); let border = |x|x;//Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb)).enclose(x);
let iter = | |model.clips().clone().into_iter(); let iter = | |model.clips().clone().into_iter();
let height = clips.read().unwrap().len() as u16; let height = clips.read().unwrap().len() as u16;
Tui::bg(Reset, Fixed::y(height, on_bg(border(Map::new(iter, move|clip: Arc<RwLock<MidiClip>>, i|{ Tui::bg(Color::Reset, Fixed::y(height, on_bg(border(Map::new(iter, move|clip: Arc<RwLock<MidiClip>>, i|{
let item_height = 1; let item_height = 1;
let item_offset = i as u16 * item_height; let item_offset = i as u16 * item_height;
let selected = i == model.clip_index(); let selected = i == model.clip_index();
@ -969,15 +946,18 @@ content!(TuiOut: |self: PoolView<'a>| {
}); });
content!(TuiOut: |self: ClipLength| { content!(TuiOut: |self: ClipLength| {
use ClipLengthFocus::*;
let bars = ||self.bars_string(); let bars = ||self.bars_string();
let beats = ||self.beats_string(); let beats = ||self.beats_string();
let ticks = ||self.ticks_string(); let ticks = ||self.ticks_string();
match self.focus { match self.focus {
None => row!(" ", bars(), ".", beats(), ".", ticks()), None =>
Some(Bar) => row!("[", bars(), "]", beats(), ".", ticks()), row!(" ", bars(), ".", beats(), ".", ticks()),
Some(Beat) => row!(" ", bars(), "[", beats(), "]", ticks()), Some(ClipLengthFocus::Bar) =>
Some(Tick) => row!(" ", bars(), ".", beats(), "[", ticks()), row!("[", bars(), "]", beats(), ".", ticks()),
Some(ClipLengthFocus::Beat) =>
row!(" ", bars(), "[", beats(), "]", ticks()),
Some(ClipLengthFocus::Tick) =>
row!(" ", bars(), ".", beats(), "[", ticks()),
} }
}); });
@ -1019,9 +999,7 @@ impl PianoHorizontal {
} }
} }
pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16) pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16) -> impl Iterator<Item=(usize, u16, usize)> {
-> impl Iterator<Item=(usize, u16, usize)>
{
(note_lo..=note_hi).rev().enumerate().map(move|(y, n)|(y, y0 + y as u16, n)) (note_lo..=note_hi).rev().enumerate().map(move|(y, n)|(y, y0 + y as u16, n))
} }
@ -1292,8 +1270,18 @@ impl std::fmt::Debug for PianoHorizontal {
fn to_key (note: usize) -> &'static str { fn to_key (note: usize) -> &'static str {
match note % 12 { match note % 12 {
11 | 9 | 7 | 5 | 4 | 2 | 0 => "████▌", 11 => "████▌",
10 | 8 | 6 | 3 | 1 => " ", 10 => " ",
9 => "████▌",
8 => " ",
7 => "████▌",
6 => " ",
5 => "████▌",
4 => "████▌",
3 => " ",
2 => "████▌",
1 => " ",
0 => "████▌",
_ => unreachable!(), _ => unreachable!(),
} }
} }