convert to layout suffixes

This commit is contained in:
i do not exist 2026-07-07 16:35:52 +03:00
parent 2d64f63741
commit d8a767326c
6 changed files with 245 additions and 230 deletions

View file

@ -54,9 +54,9 @@ fn tek_draw_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Drawn<u16
Some(":sessions") => view_sessions().draw(to),
Some(":browse/title") => view_browse_title(state).draw(to),
Some(":device") => view_device(state).draw(to),
Some(":status") => h_exact(1, "TODO: Status Bar").draw(to),
Some(":status") => "TODO: Status Bar".exact_h(1).draw(to),
Some(":editor") => "TODO Editor".draw(to),
Some(":debug") => h_exact(1, format!("[{:?}]", to.area())).draw(to),
Some(":debug") => format!("[{:?}]", to.area()).exact_h(1).draw(to),
Some(_) => {
let views = state.config.views.read().unwrap();
if let Some(dsl) = views.get(dsl.src()?.unwrap()) {
@ -73,8 +73,8 @@ fn tek_draw_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Drawn<u16
pub fn draw_meter_section (to: &mut Tui, mut frags: std::str::Split<&str>) -> Drawn<u16> {
match frags.next() {
Some("input") => bg(Rgb(30, 30, 30), h_full(align_s("Input Meters"))).draw(to),
Some("output") => bg(Rgb(30, 30, 30), h_full(align_s("Output Meters"))).draw(to),
Some("input") => bg(Rgb(30, 30, 30), align_s("Input Meters").full_h()).draw(to),
Some("output") => bg(Rgb(30, 30, 30), align_s("Output Meters").full_h()).draw(to),
_ => panic!()
}
}
@ -82,10 +82,10 @@ pub fn draw_meter_section (to: &mut Tui, mut frags: std::str::Split<&str>) -> Dr
pub fn draw_tracks (to: &mut Tui, mut frags: std::str::Split<&str>, state: &App) -> Drawn<u16> {
match frags.next() {
None => "TODO tracks".draw(to),
Some("names") => state.project.view_track_names(state.color.clone()).draw(to),//bg(Rgb(40, 40, 40), w_full(align_w("Track Names")))),
Some("inputs") => bg(Rgb(40, 40, 40), w_full(align_w("Track Inputs"))).draw(to),
Some("devices") => bg(Rgb(40, 40, 40), w_full(align_w("Track Devices"))).draw(to),
Some("outputs") => bg(Rgb(40, 40, 40), w_full(align_w("Track Outputs"))).draw(to),
Some("names") => state.project.view_track_names(state.color.clone()).draw(to),//bg(Rgb(40, 40, 40), full_w(align_w("Track Names")))),
Some("inputs") => bg(Rgb(40, 40, 40), align_w("Track Inputs").full_w()).draw(to),
Some("devices") => bg(Rgb(40, 40, 40), align_w("Track Devices").full_w()).draw(to),
Some("outputs") => bg(Rgb(40, 40, 40), align_w("Track Outputs").full_w()).draw(to),
_ => panic!()
}
}
@ -104,16 +104,15 @@ pub fn draw_dialog (
Some("menu") => if let Dialog::Menu(selected, items) = &state.dialog {
let items = items.clone();
let selected = selected;
Some(wh_full(thunk(move|to: &mut Tui|{
Some(thunk(move|to: &mut Tui|{
for (index, MenuItem(item, _)) in items.0.iter().enumerate() {
y_push((2 * index) as u16,fg_bg(
if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) },
if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) },
h_exact(2, align_n(w_full(item)))
)).draw(to)?;
let f = if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) };
let b = if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) };
fg_bg(f, b, align_n(item.full_w()).exact_h(2))
.push_y((2 * index) as u16).draw(to)?;
}
Ok(Some(to.area().into()))
})))
}).full_wh())
} else {
None
}.draw(to),
@ -123,7 +122,7 @@ pub fn draw_dialog (
pub fn draw_templates (to: &mut Tui, frags: std::str::Split<&str>, state: &App) -> Drawn<u16> {
let height = (state.config.modes.len() * 2) as u16;
h_exact(height, w_min(Some(30), thunk(move |to: &mut Tui|{
thunk(move |to: &mut Tui|{
let mut index = 0;
state.config.modes.for_each(|id, profile| {
let b = if index == 0 { Rgb(70,70,70) } else { Rgb(50,50,50) };
@ -131,31 +130,28 @@ pub fn draw_templates (to: &mut Tui, frags: std::str::Split<&str>, state: &App)
let info = profile.info.get(0).map(|x|x.as_ref()).unwrap_or("<no info>");
let fg1 = Rgb(224, 192, 128);
let fg2 = Rgb(224, 128, 32);
let field_name = w_full(align_w(fg(fg1, name)));
let field_id = w_full(align_e(fg(fg2, id)));
let field_info = w_full(align_w(info));
let _ = y_push((2 * index) as u16,
h_exact(2, w_full(bg(b, south(
above(field_name, field_id),
field_info
))))).draw(to);
let field_name = align_w(fg(fg1, name)).full_w();
let field_id = align_e(fg(fg2, id)).full_w();
let field_info = align_w(info).full_w();
let _ = bg(b, south(above(field_name, field_id), field_info))
.full_w().exact_h(2).push_y((2 * index) as u16).draw(to);
index += 1;
});
Ok(Some(to.area().into()))
}))).draw(to)
}).min_w(30).exact_h(height).draw(to)
}
/// ```
/// let _ = tek::view_logo();
/// ```
pub fn view_logo () -> impl Draw<Tui> {
wh_exact(Some(32), Some(7), bold(true, fg(Rgb(240, 200, 180), south!{
h_exact(1, ""),
h_exact(1, ""),
h_exact(1, "~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~"),
h_exact(1, east("~~~~ ║ ~ ╟─╌ ~╟─< ~~ ", east(fg(Rgb(230,100,40), "v0.3.0"), " ~~"))),
h_exact(1, "~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~"),
})))
bold(true, fg(Rgb(240, 200, 180), south!{
"".exact_h(1),
"".exact_h(1),
"~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~".exact_h(1),
east("~~~~ ║ ~ ╟─╌ ~╟─< ~~ ", east(fg(Rgb(230,100,40), "v0.3.0"), " ~~")).exact_h(1),
"~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~".exact_h(1),
})).exact_wh(32, 7)
}
/// ```
@ -166,12 +162,12 @@ pub fn view_logo () -> impl Draw<Tui> {
pub fn view_transport (play: bool, bpm: &str, beat: &str, time: &str) -> impl Draw<Tui> {
let theme = ItemTheme::G[96];
bg(Black, east!(above(
wh_full(align_w(button_play_pause(play, false))),
wh_full(align_e(east!(
align_w(button_play_pause(play, false)).full_wh(),
align_e(east!(
field_h(theme, "BPM", bpm),
field_h(theme, "Beat", beat),
field_h(theme, "Time", time),
)))
)).full_wh()
)))
}
@ -186,8 +182,8 @@ pub fn view_status (sel: Option<&str>, sr: &str, buf: &str, lat: &str) -> impl D
let buf = field_h(theme, "Buf", buf);
let lat = field_h(theme, "Lat", lat);
bg(Black, east!(above(
wh_full(align_w(sel.map(|sel|field_h(theme, "Selected", sel)))),
wh_full(align_e(east!(sr, buf, lat))),
align_w(sel.map(|sel|field_h(theme, "Selected", sel))).full_wh(),
align_e(east!(sr, buf, lat)).full_wh(),
)))
}
@ -200,14 +196,14 @@ pub fn view_status (sel: Option<&str>, sr: &str, buf: &str, lat: &str) -> impl D
pub fn button_play_pause (playing: bool, compact: bool) -> impl Draw<Tui> {
bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
either(compact,
thunk(move|to: &mut Tui|w_exact(9, either(playing,
thunk(move|to: &mut Tui|either(playing,
fg(Rgb(0, 255, 0), " PLAYING "),
fg(Rgb(255, 128, 0), " STOPPED "))
).draw(to)),
thunk(move|to: &mut Tui|w_exact(5, either(playing,
fg(Rgb(255, 128, 0), " STOPPED "),
).exact_w(9).draw(to)),
thunk(move|to: &mut Tui|either(playing,
fg(Rgb(0, 255, 0), south(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",)))
).draw(to)),
fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",)),
).exact_w(5).draw(to)),
)
)
}
@ -218,8 +214,13 @@ pub fn button_play_pause (playing: bool, compact: bool) -> impl Draw<Tui> {
button_add: impl Draw<Tui>,
content: impl Draw<Tui>,
) -> impl Draw<Tui> {
west(h_full(w_exact(4, align_nw(button_add))),
east(w_exact(20, h_full(align_nw(button))), wh_full(align_c(content))))
west(
align_nw(button_add).exact_w(4).full_h(),
east(
align_nw(button).full_h().exact_w(20),
align_c(content).full_wh()
)
)
}
/// ```
@ -228,8 +229,8 @@ pub fn button_play_pause (playing: bool, compact: bool) -> impl Draw<Tui> {
/// let _ = tek::view_wrap(bg, fg, "and then blue, too!");
/// ```
pub fn view_wrap (bg: Color, fg: Color, content: impl Draw<Tui>) -> impl Draw<Tui> {
let left = fg_bg(bg, Reset, w_exact(1, y_repeat("")));
let right = fg_bg(bg, Reset, w_exact(1, y_repeat("")));
let left = fg_bg(bg, Reset, y_repeat("").exact_w(1));
let right = fg_bg(bg, Reset, y_repeat("").exact_w(1));
east(left, west(right, fg_bg(fg, bg, content)))
}
@ -256,7 +257,7 @@ pub fn view_meter <'a> (label: &'a str, value: f32) -> impl Draw<Tui> + 'a {
let c = if value >= 0.0 { Red }
else if value >= -3.0 { Yellow }
else { Green };
south!(f, wh_exact(Some(w), Some(1), bg(c, ())))
south!(f, bg(c, ()).exact_wh(w, 1))
}
pub fn view_meters (values: &[f32;2]) -> impl Draw<Tui> + use<'_> {
@ -284,14 +285,14 @@ pub fn view_sample_info_v (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tu
let a = thunk(move|to: &mut Tui|{
let sample = sample.unwrap().read().unwrap();
let theme = sample.color;
w_exact(20, south!(
w_full(align_w(field_h(theme, "Name ", format!("{:<10}", sample.name.clone())))),
w_full(align_w(field_h(theme, "Length", format!("{:<8}", sample.channels[0].len())))),
w_full(align_w(field_h(theme, "Start ", format!("{:<8}", sample.start)))),
w_full(align_w(field_h(theme, "End ", format!("{:<8}", sample.end)))),
w_full(align_w(field_h(theme, "Trans ", "0"))),
w_full(align_w(field_h(theme, "Gain ", format!("{}", sample.gain)))),
)).draw(to)
south!(
align_w(field_h(theme, "Name ", format!("{:<10}", sample.name.clone()))).full_w(),
align_w(field_h(theme, "Length", format!("{:<8}", sample.channels[0].len()))).full_w(),
align_w(field_h(theme, "Start ", format!("{:<8}", sample.start))).full_w(),
align_w(field_h(theme, "End ", format!("{:<8}", sample.end))).full_w(),
align_w(field_h(theme, "Trans ", "0")).full_w(),
align_w(field_h(theme, "Gain ", format!("{}", sample.gain))).full_w(),
).exact_w(20).draw(to)
});
let b = thunk(|to: &mut Tui|fg(Red, south!(
@ -313,7 +314,7 @@ pub fn view_sample_status (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tu
}
pub fn view_track_header (theme: ItemTheme, content: impl Draw<Tui>) -> impl Draw<Tui> {
w_exact(12, bg(theme.darker.term, w_full(align_e(content))))
bg(theme.darker.term, align_e(content).full_w()).exact_w(12)
}
pub fn view_ports_status <'a, T: JackPort> (theme: ItemTheme, title: &'a str, ports: &'a [T])
@ -322,22 +323,22 @@ pub fn view_ports_status <'a, T: JackPort> (theme: ItemTheme, title: &'a str, po
let ins = ports.len() as u16;
let frame = Outer(true, Style::default().fg(g(96)));
let iter = move||ports.iter();
let names = iter_south(iter, move|port, index|h_full(align_w(format!(" {index} {}", port.port_name()))));
let names = iter_south(iter, move|port, index|align_w(format!(" {index} {}", port.port_name())).full_h());
let field = field_v(theme, title, names);
wh_exact(Some(20), Some(1 + ins), border(true, frame, wh_exact(Some(20), Some(1 + ins), field)))
border(true, frame, field.exact_wh(20, 1 + ins)).exact_wh(20, 1 + ins)
}
pub fn view_io_ports <'a, T: PortsSizes<'a>> (
fg: Color, bg: Color, items: impl Fn()->T + Send + Sync + 'a
) -> impl Draw<Tui> + 'a {
type Item<'a> = (usize, &'a Arc<str>, &'a [Connect], usize, usize);
iter(items, move|(_index, name, connections, y, y2): Item<'a>, _| {
y_push(y as u16, h_exact((y2-y) as u16,
south(h_full(bold(true, fg_bg(fg, bg, align_w(east(" 󰣲 ", name))))),
iter(||connections.iter(), move|connect: &'a Connect, index|y_push(
index as u16, h_exact(1, align_w(bold(false, fg_bg(fg, bg, &connect.info))))
)))))
})
iter(items,
move|(_index, name, connections, y, y2): Item<'a>, _| south(
bold(true, fg_bg(fg, bg, align_w(east(" 󰣲 ", name)))).full_h(),
iter(||connections.iter(), move|connect: &'a Connect, index|{
align_w(bold(false, fg_bg(fg, bg, &connect.info)).exact_h(1)).push_y(index as u16)
})
).exact_h((y2 - y) as u16).push_y(y as u16))
}
pub fn view_scenes_clips <'a, S: ScenesSizes<'a>> (
@ -348,7 +349,7 @@ pub fn view_scenes_clips <'a, S: ScenesSizes<'a>> (
size: &Sizer,
editing: bool,
) -> impl Draw<Tui> {
let status = wh_full(align_se(fg(Green, format!("{}x{}", size.w(), size.h()))));
let status = align_se(fg(Green, format!("{}x{}", size.w(), size.h()))).full_wh();
let tracks = iter_once(tracks, move|(track_index, track, _, _), _| {
let scenes = iter_once(scenes(), move|(scene_index, scene, _, _), _| {
let (name, theme): (Arc<str>, ItemTheme) = scene_name_theme(scene, track_index);
@ -357,19 +358,21 @@ pub fn view_scenes_clips <'a, S: ScenesSizes<'a>> (
let w = scene_w(track, select, track_index, editor);
let y = scene_y(select, scene_index, editor);
let is_selected = scene_sel(select, track_index, scene_index, editing);
wh_exact(Some(w), Some(y), below(
wh_full(Outer(true, Style::default().fg(o))),
wh_full(below(
below(
Outer(true, Style::default().fg(o)).full_wh(),
below(
below(
fg_bg(o, b, wh_full("")),
wh_full(align_nw(fg_bg(f, b, bold(true, name)))),
fg_bg(o, b, "".full_wh()),
align_nw(fg_bg(f, b, bold(true, name))).full_wh(),
),
wh_full(when(is_selected, editor.map(|e|e.view())))))))
when(is_selected, editor.map(|e|e.view())).full_wh()
).full_wh()
).exact_wh(w, y)
});
w_exact(track.width as u16, h_full(scenes))
scenes.full_h().exact_w(track.width as u16)
});
return size.of(wh_full(above(status, tracks)));
return size.of(above(status, tracks).full_wh());
fn scene_name_theme (scene: &Scene, track_index: usize) -> (Arc<str>, ItemTheme) {
if let Some(Some(clip)) = &scene.clips.get(track_index) {
@ -436,42 +439,48 @@ pub fn view_track_names (
button_2("T", "+", false),
button_2("S", "+", false));
view_track_row_section(theme, button, button_2, bg(theme.darker.term,
h_exact(2, thunk(|to: &mut Tui|{
thunk(|to: &mut Tui|{
for (index, track, x1, _x2) in tracks {
x_push(x1 as u16, w_exact(track_width(index, track),
bg(if selected.track() == Some(index) {
track.color.light.term
} else {
track.color.base.term
}, south(w_full(align_nw(east(
format!("·t{index:02} "),
fg(Rgb(255, 255, 255), bold(true, &track.name))
))), ""))) ).draw(to)?;
let b = if selected.track() == Some(index) {
track.color.light.term
} else {
track.color.base.term
};
bg(b, south(align_nw(east(
format!("·t{index:02} "),
fg(Rgb(255, 255, 255), bold(true, &track.name))
)).full_w(), ""))
.exact_w(track_width(index, track))
.push_x(x1 as u16)
.draw(to)?;
}
Ok(Some(XYWH(0, 0, 0, 0)))
}))))
}).exact_h(2)))
}
pub fn view_track_outputs (
theme: ItemTheme, tracks: impl TracksSizes<'_>, midi_outs: impl Iterator<Item = &MidiOutput>,
) -> impl Draw<Tui> {
view_track_row_section(theme,
south(w_full(align_w(button_2("o", "utput", false))),
south(align_w(button_2("o", "utput", false)).full_w(),
thunk(|to: &mut Tui|{
for port in midi_outs {
w_full(align_w(port.port_name())).draw(to);
align_w(port.port_name()).full_w().draw(to);
}
Ok(Some(XYWH(0, 0, 0, 0)))
})),
button_2("O", "+", false),
bg(theme.darker.term, align_w(thunk(|to: &mut Tui|{
for (index, track, _x1, _x2) in tracks {
let f = Rgb(255, 255, 255);
let b = track.color.dark.term;
let iter = ||track.sequencer.midi_outs.iter();
let draw = |port: &MidiOutput, _|fg(Rgb(255, 255, 255),
h_exact(1, bg(track.color.dark.term, w_full(align_w(
format!("·o{index:02} {}", port.port_name()))))));
w_exact(track_width(index, track),
align_nw(h_full(iter_south(iter, draw)))).draw(to)?;
let draw = |port: &MidiOutput, _|fg(f, bg(b, align_w(
format!("·o{index:02} {}", port.port_name()).full_w()
)).exact_h(1));
align_nw(iter_south(iter, draw).full_h())
.exact_w(track_width(index, track))
.draw(to)?;
}
Ok(Some(XYWH(0, 0, 0, 0)))
}))))
@ -483,18 +492,17 @@ pub fn view_track_inputs (
view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false),
bg(theme.darker.term, align_w(thunk(move|to: &mut Tui|{
for (index, track, _x1, _x2) in tracks {
wh_exact(Some(track_width(index, track)), Some(height + 1),
align_nw(south(
bg(track.color.base.term,
w_full(align_w(east!(
either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "),
either(track.sequencer.recording, fg(Red, "●rec "), "·rec "),
either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "),
)))),
iter_south(||track.sequencer.midi_ins.iter(),
|port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term,
w_full(align_w(format!("·i{index:02} {}", port.port_name()))))))))
.draw(to)?;
align_nw(south(
bg(track.color.base.term,
align_w(east!(
either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "),
either(track.sequencer.recording, fg(Red, "●rec "), "·rec "),
either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "),
)).full_w()),
iter_south(||track.sequencer.midi_ins.iter(),
|port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term,
align_w(format!("·i{index:02} {}", port.port_name())).full_w()))
)).exact_wh(track_width(index, track), height + 1).draw(to)?;
}
Ok(Some(XYWH(0, 0, 0, 0)))
}))))
@ -506,12 +514,12 @@ pub fn view_scenes_names (
editor: Option<&MidiEditor>,
editing: bool,
) -> impl Draw<Tui> {
w_exact(20, thunk(move |to: &mut Tui|{
thunk(move |to: &mut Tui|{
for (index, scene, ..) in scenes {
view_scene_name(select, editor, index, scene, editing).draw(to)?;
}
Ok(Some(XYWH(1, 1, 1, 1)))
}))
}).exact_w(20)
}
pub fn view_scene_name (
@ -526,18 +534,18 @@ pub fn view_scene_name (
} else {
H_SCENE as u16
};
let a = w_full(align_w(east(format!("·s{index:02} "),
fg(g(255), bold(true, &scene.name)))));
let b = when(select.scene() == Some(index) && editing,
wh_full(align_nw(south(
editor.as_ref().map(|e|e.clip_status()),
editor.as_ref().map(|e|e.edit_status())))));
let a = align_w(east(format!("·s{index:02} "),
fg(g(255), bold(true, &scene.name)))).full_w();
let b = when(select.scene() == Some(index) && editing, align_nw(south(
editor.as_ref().map(|e|e.clip_status()),
editor.as_ref().map(|e|e.edit_status()))).full_wh());
let c = if select.scene() == Some(index) {
scene.color.light.term
} else {
scene.color.base.term
};
wh_exact(Some(20), Some(h), bg(c, align_nw(south(a, b))))
bg(c, align_nw(south(a, b)))
.exact_wh(20, h)
}
pub fn view_midi_ins_status (theme: ItemTheme, track: Option<&Track>) -> impl Draw<Tui> {
@ -561,10 +569,11 @@ pub fn view_track_per <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
) -> impl Draw<Tui> {
iter_east(tracks, move|(index, track, x1, x2): (usize, &Track, usize, usize), _|{
w_exact((x2 - x1) as u16, fg_bg(
fg_bg(
track.color.lightest.term,
track.color.base.term,
callback(index, track)))
callback(index, track)
).exact_w((x2 - x1) as u16)
})
}
@ -573,27 +582,34 @@ pub fn view_per_track () -> impl Draw<Tui> {}
pub fn view_per_track_top () -> impl Draw<Tui> {}
pub fn view_inputs (tracks: impl TracksSizes<'_>, midi_ins: &[MidiInput]) -> impl Draw<Tui> {
let title_1 = wh_exact(Some(20), Some(1), align_w(button_3("i", "nput ", format!("{}", midi_ins.len()), false)));
let title_2 = wh_exact(Some(4), Some(1), w_exact(4, button_2("I", "+", false)));
let title_1 = align_w(button_3("i", "nput ", format!("{}", midi_ins.len()), false)).exact_wh(20, 1);
let title_2 = button_2("I", "+", false).exact_wh(4, 1);
east(title_1, west(title_2, thunk(move|to: &mut Tui|{
for (_index, track, x1, _x2) in tracks {
south(
x_push(x1 as u16, bg(track.color.dark.term, align_w(w_exact(track.width as u16, east!(
bg(track.color.dark.term, align_w(east!(
either(track.sequencer.monitoring, fg(Green, "mon "), "mon "),
either(track.sequencer.recording, fg(Red, "rec "), "rec "),
either(track.sequencer.overdub, fg(Yellow, "dub "), "dub "),
))))),
).exact_w(track.width as u16))).push_x(x1 as u16),
thunk(move |to: &mut Tui|{
for (index, port) in midi_ins.iter().enumerate() {
x_push(index as u16 * 10, h_exact(1, east(w_exact(20, align_w(east("", bold(true, fg(Rgb(255,255,255), port.port_name()))))),
west(w_exact(4, ()), thunk(move|to: &mut Tui|{
bg(track.color.darker.term, align_w(w_exact(track.width as u16, east!(
either(track.sequencer.monitoring, fg(Green, ""), " · "),
either(track.sequencer.recording, fg(Red, ""), " · "),
either(track.sequencer.overdub, fg(Yellow, ""), " · "),
)))).draw(to);
todo!()
}))))).draw(to);
east(
align_w(east(
"",
bold(true, fg(Rgb(255,255,255), port.port_name()))
)).exact_w(20),
west(
().exact_w(4),
thunk(move|to: &mut Tui|{
bg(track.color.darker.term, align_w(east!(
either(track.sequencer.monitoring, fg(Green, ""), " · "),
either(track.sequencer.recording, fg(Red, ""), " · "),
either(track.sequencer.overdub, fg(Yellow, ""), " · "),
).exact_w(track.width as u16))).draw(to);
todo!()
}))
).push_x(index as u16 * 10).exact_h(1).draw(to);
}
todo!()
})
@ -611,52 +627,47 @@ pub fn view_outputs (
) -> impl Draw<Tui> {
let list = south(
h_exact(1, w_full(align_w(button_3(
align_w(button_3(
"o", "utput", format!("{}", midi_outs.len()), false
)))),
h_exact(height - 1, wh_full(align_nw(thunk(|to: &mut Tui|{
)).full_w().exact_h(1),
align_nw(thunk(|to: &mut Tui|{
for (_index, port) in midi_outs.iter().enumerate() {
h_exact(1,w_full(east(
east(
align_w(east("", fg(Rgb(255,255,255), bold(true, port.port_name())))),
w_full(align_e(format!("{}/{} ",
align_e(format!("{}/{} ",
port.port().get_connections().len(),
port.connections.len())))))).draw(to)?;
port.connections.len())
).full_w().exact_h(1)).full_w().draw(to)?;
for (index, conn) in port.connections.iter().enumerate() {
h_exact(1, w_full(align_w(format!(" c{index:02}{}", conn.info()))))
.draw(to)?;
align_w(format!(" c{index:02}{}", conn.info())).full_w().exact_h(1).draw(to)?;
}
}
todo!();
}))))
})).full_wh().exact_h(height - 1)
);
h_exact(height, view_track_row_section(theme, list, button_2("O", "+", false),
bg(theme.darker.term, align_w(w_full(
thunk(|to: &mut Tui|{
for (index, track, _x1, _x2) in tracks {
w_exact(track_width(index, track),
thunk(|to: &mut Tui|{
h_exact(1, align_w(east(
either(true, fg(Green, "play "), "play "),
either(false, fg(Yellow, "solo "), "solo "),
))).draw(to)?;
for (_index, port) in midi_outs.iter().enumerate() {
h_exact(1, align_w(east(
either(true, fg(Green, ""), " · "),
either(false, fg(Yellow, ""), " · "),
))).draw(to)?;
for (_index, _conn) in port.connections.iter().enumerate() {
h_exact(1, w_full("")).draw(to)?;
}
}
todo!()
})
).draw(to);
}
todo!()
})
)))
))
view_track_row_section(theme, list, button_2("O", "+", false),
bg(theme.darker.term, align_w(thunk(|to: &mut Tui|{
for (index, track, _x1, _x2) in tracks {
thunk(|to: &mut Tui|{
align_w(east(
either(true, fg(Green, "play "), "play "),
either(false, fg(Yellow, "solo "), "solo "),
)).exact_h(1).draw(to)?;
for (_index, port) in midi_outs.iter().enumerate() {
align_w(east(
either(true, fg(Green, ""), " · "),
either(false, fg(Yellow, ""), " · "),
)).exact_h(1).draw(to)?;
for (_index, _conn) in port.connections.iter().enumerate() {
"".full_w().exact_h(1).draw(to)?;
}
}
todo!()
}).exact_w(track_width(index, track)).draw(to);
}
todo!()
}).full_w()))).exact_h(height)
}
pub fn view_track_devices (
@ -668,24 +679,25 @@ pub fn view_track_devices (
view_track_row_section(theme,
button_3("d", "evice", format!("{}", track.map(|t|t.devices.len()).unwrap_or(0)), false),
button_2("D", "+", false),
iter_once(tracks, move|(_, track, _x1, _x2), index| wh_exact(
Some(track_width(index, track)),
Some(h + 1),
bg(track.color.dark.term, align_nw(iter_south(move||0..h,
|_, _index|wh_exact(Some(track.width as u16), Some(2),
fg_bg(
ItemTheme::G[32].lightest.term,
ItemTheme::G[32].dark.term,
align_nw(format!(" · {}", "--"))
)
)))))))
iter_once(tracks, move|(_, track, _x1, _x2), index|bg(
track.color.dark.term,
align_nw(iter_south(move||0..h,
|_, _index|fg_bg(
ItemTheme::G[32].lightest.term,
ItemTheme::G[32].dark.term,
align_nw(format!(" · {}", "--"))
).exact_wh(track.width as u16, 2)
))).exact_wh(
Some(track_width(index, track)),
Some(h + 1),
)))
}
pub fn per_track <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
tracks: impl Fn() -> U + Send + Sync + 'a,
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
) -> impl Draw<Tui> + 'a {
per_track_top(tracks, move|index, track|h_full(align_y(callback(index, track))))
per_track_top(tracks, move|index, track|align_y(callback(index, track).full_h()))
}
pub fn per_track_top <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
@ -694,10 +706,12 @@ pub fn per_track_top <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
) -> impl Draw<Tui> + 'a {
align_x(bg(Reset, iter_east(tracks,
move|(index, track, x1, x2): (usize, &'a Track, usize, usize), _|{
w_exact((x2 - x1) as u16, fg_bg(
fg_bg(
track.color.lightest.term,
track.color.base.term,
callback(index, track))) })))
callback(index, track)
).exact_w((x2 - x1) as u16)
})))
}
pub fn field_h <T: Screen> (theme: ItemTheme, head: impl Draw<T>, body: impl Draw<T>) -> impl Draw<T> {
@ -710,19 +724,19 @@ pub fn view_sessions () -> impl Draw<Tui> {
let h = 6;
let w = Some(30);
let f = Rgb(224, 192, 128);
h_exact(h, w_min(w, thunk(move |to: &mut Tui|{
thunk(move |to: &mut Tui|{
for (index, name) in ["session1", "session2", "session3"].iter().enumerate() {
let b = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) };
let y = (2 * index) as u16;
let h = 2;
y_push(y, h_exact(h, w_full(bg(b, align_w(fg(f, *name)))))).draw(to)?;
bg(b, align_w(fg(f, *name))).full_w().exact_h(h).push_y(y).draw(to)?;
}
Ok(Some(to.area().into()))
})))
}).min_w(w).exact_h(h)
}
pub fn view_browse_title (state: &App) -> impl Draw<Tui> {
w_full(align_w(field_v(ItemTheme::default(),
align_w(field_v(ItemTheme::default(),
match state.dialog.browser_target().unwrap() {
BrowseTarget::SaveProject => "Save project:",
BrowseTarget::LoadProject => "Load project:",
@ -730,8 +744,8 @@ pub fn view_browse_title (state: &App) -> impl Draw<Tui> {
BrowseTarget::ExportSample(_) => "Export sample:",
BrowseTarget::ImportClip(_) => "Import clip:",
BrowseTarget::ExportClip(_) => "Export clip:",
}, h_exact(1, fg(g(96), x_repeat("🭻")))
)))
}, fg(g(96), x_repeat("🭻")).exact_h(1)
)).full_w()
}
pub fn view_device (state: &App) -> impl Draw<Tui> {
@ -742,5 +756,6 @@ pub fn view_device (state: &App) -> impl Draw<Tui> {
let b = if i == selected { Rgb(64,128,32) } else { Rgb(0,0,0) };
let l = if i == selected { "[ " } else { " " };
let r = if i == selected { " ]" } else { " " };
w_full(bg(b, east(l, west(r, "FIXME device name")))) }))
bg(b, east(l, west(r, "FIXME device name"))).full_w()
}))
}

View file

@ -241,7 +241,7 @@ impl<'a> PoolView<'a> {
//let on_bg = |x|x;//below(Repeat(" "), bg(color.darkest.term, x));
//let border = |x|x;//Outer(Style::default().fg(color.dark.term).bg(color.darkest.term)).enclose(x);
//let height = pool.clips.read().unwrap().len() as u16;
w_exact(20, h_full(origin_n(iter(
origin_n(iter(
||pool.clips().clone().into_iter(),
move|clip: Arc<RwLock<MidiClip>>, i: usize|{
let MidiClip { ref name, color, length, .. } = *clip.read().unwrap();
@ -252,13 +252,13 @@ impl<'a> PoolView<'a> {
let f = color.lightest.term;
let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") };
let length = if false { String::default() } else { format!("{length} ") };
h_exact(1, bg(b, below!(
w_full(origin_w(fg(f, bold(selected, name)))),
w_full(origin_e(fg(f, bold(selected, length)))),
w_full(origin_w(when(selected, bold(true, fg(g(255), ""))))),
w_full(origin_e(when(selected, bold(true, fg(g(255), ""))))),
)))
}))))
bg(b, below!(
origin_w(fg(f, bold(selected, name))).full_w(),
origin_e(fg(f, bold(selected, length))).full_w(),
origin_w(when(selected, bold(true, fg(g(255), "")))).full_w(),
origin_e(when(selected, bold(true, fg(g(255), "")))).full_w(),
)).exact_h(1)
})).full_h().exact_w(20)
}
}
@ -315,7 +315,7 @@ impl Browse {
impl Browse {
fn tui (&self) -> impl Draw<Tui> {
let item = |entry, _index|w_full(origin_w(entry));
let item = |entry, _index|origin_w(entry).full_w();
let iterate = ||EntriesIterator {
offset: 0,
index: 0,

View file

@ -98,17 +98,14 @@ impl MidiEditor {
let (_color, name, length, looped) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
(clip.color, clip.name.clone(), clip.length, clip.looped)
} else { (ItemTheme::G[64], String::new().into(), 0, false) };
w_exact(20, south!(
w_full(origin_w(east(
button_2("f2", "name ", false),
w_full(origin_e(fg(Rgb(255, 255, 255), format!("{name} "))))))),
w_full(origin_w(east(
button_2("l", "ength ", false),
w_full(origin_e(fg(Rgb(255, 255, 255), format!("{length} "))))))),
w_full(origin_w(east(
button_2("r", "epeat ", false),
w_full(origin_e(fg(Rgb(255, 255, 255), format!("{looped} "))))))),
))
south!(
origin_w(east(button_2("f2", "name ", false),
origin_e(fg(Rgb(255, 255, 255), format!("{name} "))).full_w())).full_w(),
origin_w(east(button_2("l", "ength ", false),
origin_e(fg(Rgb(255, 255, 255), format!("{length} "))).full_w())).full_w(),
origin_w(east(button_2("r", "epeat ", false),
origin_e(fg(Rgb(255, 255, 255), format!("{looped} "))).full_w())).full_w(),
).exact_w(20)
}
pub fn edit_status (&self) -> impl Draw<Tui> + '_ {
let (_color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
@ -121,20 +118,17 @@ impl MidiEditor {
let note_name = format!("{:4}", note_pitch_to_name(note_pos));
let note_pos = format!("{:>3}", note_pos);
let note_len = format!("{:>4}", self.get_note_len());
w_exact(20, south!(
w_full(origin_w(east(
button_2("t", "ime ", false),
w_full(origin_e(fg(Rgb(255, 255, 255),
format!("{length} /{time_zoom} +{time_pos} "))))))),
w_full(origin_w(east(
button_2("z", "lock ", false),
w_full(origin_e(fg(Rgb(255, 255, 255),
format!("{time_lock}"))))))),
w_full(origin_w(east(
button_2("x", "note ", false),
w_full(origin_e(fg(Rgb(255, 255, 255),
format!("{note_name} {note_pos} {note_len}"))))))),
))
south!(
origin_w(east(button_2("t", "ime ", false),
origin_e(fg(Rgb(255, 255, 255),
format!("{length} /{time_zoom} +{time_pos} "))).full_w())).full_w(),
origin_w(east(button_2("z", "lock ", false),
origin_e(fg(Rgb(255, 255, 255),
format!("{time_lock}"))).full_w())).full_w(),
origin_w(east(button_2("x", "note ", false),
origin_e(fg(Rgb(255, 255, 255),
format!("{note_name} {note_pos} {note_len}"))).full_w())).full_w(),
).exact_w(20)
}
}

View file

@ -27,8 +27,14 @@ impl_has!(Sizer: |self: PianoHorizontal| self.size);
impl View<Tui> for PianoHorizontal {
fn view (&self) -> impl Draw<Tui> {
south(
east(w_exact(5, format!("{}x{}", self.size.w(), self.size.h())), self.timeline()),
east(self.keys(), self.size.of(below(wh_full(self.notes()), wh_full(self.cursor())))),
east(
format!("{}x{}", self.size.w(), self.size.h()).exact_w(5),
self.timeline()
),
east(
self.keys(),
self.size.of(below(self.notes().full_wh(), self.cursor().full_wh()))
),
)
}
}
@ -203,7 +209,7 @@ impl PianoHorizontal {
let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0)));
let off_style = Some(Style::default().fg(g(255)));
let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.term).bold());
h_full(w_exact(self.keys_width, thunk(move|to: &mut Tui|{
thunk(move|to: &mut Tui|{
let xywh = to.area().into();
let XYWH(x, y0, _w, _h) = xywh;
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
@ -218,11 +224,11 @@ impl PianoHorizontal {
};
}
Ok(Some(xywh))
})))
}).exact_w(self.keys_width).full_h()
}
fn timeline (&self) -> impl Draw<Tui> + '_ {
w_full(h_exact(1, thunk(move|to: &mut Tui|{
thunk(move|to: &mut Tui|{
let xywh = to.area().into();
let XYWH(x, y, w, _h) = xywh;
let style = Some(Style::default().dim());
@ -234,7 +240,7 @@ impl PianoHorizontal {
}
}
Ok(Some(xywh))
})))
}).exact_h(1).full_w()
}
}

View file

@ -40,9 +40,9 @@ impl_draw!(|self: Log10Meter, to: Tui| {
});
fn draw_meters (meters: &[f32]) -> impl Draw<Tui> + use<'_> {
bg(Black, w_exact(2, iter_east_fixed(1, ||meters.iter(), |value, _index|{
h_full(RmsMeter(*value))
})))
bg(Black, iter_east_fixed(1, ||meters.iter(), |value, _index|{
RmsMeter(*value).full_h()
}).exact_w(2))
}
pub fn to_log10 (samples: &[f32]) -> f32 {

2
tengri

@ -1 +1 @@
Subproject commit 1f60b43f616ff49ddd8187bcca8d31e9b6597cec
Subproject commit 09463649c673b0d883ca18746a36aa86c6bd114f