mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
Compare commits
2 commits
b4761a9679
...
a67481ab04
| Author | SHA1 | Date | |
|---|---|---|---|
| a67481ab04 | |||
| 944fcfa017 |
1 changed files with 108 additions and 96 deletions
|
|
@ -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(Color::Rgb(64,64,64), Color::Rgb(32,32,32), "")),
|
Fill::xy(Tui::fg_bg(Rgb(64,64,64), Rgb(32,32,32), "")),
|
||||||
Fixed::xy(30, 15, Tui::fg_bg(Color::Rgb(255,255,255), Color::Rgb(16,16,16), Bsp::b(
|
Fixed::xy(30, 15, Tui::fg_bg(Rgb(255,255,255), 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(Color::Rgb(255,255,255), format!("{}", a));
|
let option = |a,i|Tui::fg(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(Color::Rgb(255,192,0), if let Some(Token {
|
Fixed::x(15, Align::w(Tui::bold(true, Tui::fg(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(Color::Rgb(255,255,255), if let Some(Token {
|
Bsp::e(" ", Tui::fg(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,24 +134,35 @@ 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
|
5 // FIXME
|
||||||
//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_inputs() + self.h_outputs() + 11)
|
self.h().saturating_sub(
|
||||||
|
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 {
|
||||||
1 + self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
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 {
|
||||||
1 + self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
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.
|
||||||
|
|
@ -255,13 +266,14 @@ 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::s(self.inputs(), x);
|
let ins = |x|Bsp::n(self.inputs(), x);
|
||||||
let tracks = |x|Bsp::s(self.tracks(), x);
|
let tracks = |x|Bsp::s(self.tracks(), x);
|
||||||
let outs = |x|Bsp::n(self.outputs(), x);
|
let devices = |x|Bsp::s(self.devices(), x);
|
||||||
let bg = |x|Tui::bg(Color::Reset, x);
|
let outs = |x|Bsp::s(self.outputs(), 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);
|
||||||
ins(tracks(outs(bg(self.scenes()))))
|
outs(tracks(devices(ins(bg(self.scenes())))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,10 +287,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().saturating_sub(1),
|
inputs_height: app.h_inputs(),
|
||||||
inputs_count: app.midi_ins.len(),
|
inputs_count: app.midi_ins.len(),
|
||||||
|
|
||||||
outputs_height: app.h_outputs().saturating_sub(1),
|
outputs_height: app.h_outputs(),
|
||||||
outputs_count: app.midi_outs.len(),
|
outputs_count: app.midi_outs.len(),
|
||||||
|
|
||||||
scenes_height: app.h_scenes_area(),
|
scenes_height: app.h_scenes_area(),
|
||||||
|
|
@ -306,12 +318,57 @@ 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(Color::Reset, Bsp::s(
|
Tui::bg(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,
|
||||||
|
|
@ -364,14 +421,6 @@ 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:"))
|
||||||
|
|
@ -409,10 +458,7 @@ 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(
|
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), move|i, t|{
|
||||||
self.width_mid,
|
|
||||||
||self.tracks_with_sizes_scrolled(),
|
|
||||||
move|i, t|{
|
|
||||||
let mute = false;
|
let mute = false;
|
||||||
let solo = false;
|
let solo = false;
|
||||||
let mute = if mute { White } else { t.color.darkest.rgb };
|
let mute = if mute { White } else { t.color.darkest.rgb };
|
||||||
|
|
@ -433,34 +479,14 @@ impl<'a> ArrangerView<'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, per_track_top(
|
.middle(self.width_mid,
|
||||||
self.width_mid,
|
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), |_, t|io_conns(
|
||||||
||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 {
|
||||||
|
|
||||||
|
|
@ -689,17 +715,14 @@ 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, "▐");
|
let left = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV("▐")));
|
||||||
let right = Tui::fg_bg(bg, Reset, "▌");
|
let right = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV("▌")));
|
||||||
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, K, L> (
|
pub(crate) fn button_2 <'a> (
|
||||||
key: K, label: L, editing: bool,
|
key: impl Content<TuiOut> + 'a, label: impl Content<TuiOut> + 'a, editing: bool,
|
||||||
) -> impl Content<TuiOut> + 'a where
|
) -> impl Content<TuiOut> + 'a {
|
||||||
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), "▐"))
|
||||||
|
|
@ -927,7 +950,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(Color::Reset, Fixed::y(height, on_bg(border(Map::new(iter, move|clip: Arc<RwLock<MidiClip>>, i|{
|
Tui::bg(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();
|
||||||
|
|
@ -946,18 +969,15 @@ 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 =>
|
None => row!(" ", bars(), ".", beats(), ".", ticks()),
|
||||||
row!(" ", bars(), ".", beats(), ".", ticks()),
|
Some(Bar) => row!("[", bars(), "]", beats(), ".", ticks()),
|
||||||
Some(ClipLengthFocus::Bar) =>
|
Some(Beat) => row!(" ", bars(), "[", beats(), "]", ticks()),
|
||||||
row!("[", bars(), "]", beats(), ".", ticks()),
|
Some(Tick) => row!(" ", bars(), ".", beats(), "[", ticks()),
|
||||||
Some(ClipLengthFocus::Beat) =>
|
|
||||||
row!(" ", bars(), "[", beats(), "]", ticks()),
|
|
||||||
Some(ClipLengthFocus::Tick) =>
|
|
||||||
row!(" ", bars(), ".", beats(), "[", ticks()),
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -999,7 +1019,9 @@ impl PianoHorizontal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16) -> impl Iterator<Item=(usize, u16, usize)> {
|
pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16)
|
||||||
|
-> 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1270,18 +1292,8 @@ 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 => "████▌",
|
11 | 9 | 7 | 5 | 4 | 2 | 0 => "████▌",
|
||||||
10 => " ",
|
10 | 8 | 6 | 3 | 1 => " ",
|
||||||
9 => "████▌",
|
|
||||||
8 => " ",
|
|
||||||
7 => "████▌",
|
|
||||||
6 => " ",
|
|
||||||
5 => "████▌",
|
|
||||||
4 => "████▌",
|
|
||||||
3 => " ",
|
|
||||||
2 => "████▌",
|
|
||||||
1 => " ",
|
|
||||||
0 => "████▌",
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue