From a938b6898090188c2b7fc8b077813efda3352622 Mon Sep 17 00:00:00 2001 From: i do not exist Date: Tue, 4 Aug 2026 12:24:39 +0300 Subject: [PATCH] update for unowned draw --- src/device/arrange.rs | 204 ++++++++++++++++++++++--- src/device/editor/piano.rs | 28 ++-- src/device/sampler.rs | 60 ++++---- src/tek.rs | 304 ++++--------------------------------- tengri | 2 +- 5 files changed, 262 insertions(+), 336 deletions(-) diff --git a/src/device/arrange.rs b/src/device/arrange.rs index 92cdbc23..5cbc57c9 100644 --- a/src/device/arrange.rs +++ b/src/device/arrange.rs @@ -439,10 +439,18 @@ pub trait ScenesView: HasEditor + HasSelection + HasSceneScroll + HasClipsSize + fn w_mid (&self) -> u16; fn view_scenes_names (&self) -> impl Draw { - view_scenes_names( - self.scenes_with_sizes(), self.selection(), self.editor(), self.is_editing() - ) + let select = self.selection(); + let editor = self.editor(); + let editing = self.is_editing(); + draw(move |to: &mut Tui|{ + for (index, scene, ..) in self.scenes_with_sizes() { + view_scene_name(select, editor, index, scene, editing).draw(to)?; + } + Ok(Some(XYWH(1, 1, 1, 1))) + }) + .exact_w(20) } + fn scenes_with_sizes (&self) -> impl ScenesSizes<'_> { let mut y = 0; self.scenes().iter().enumerate().skip(self.scene_scroll()).map_while(move|(s, scene)|{ @@ -733,23 +741,84 @@ pub trait HasTrackScroll: HasTracks { pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll { /// Draw name of each track fn view_track_names (&self, theme: ItemTheme) -> impl Draw { - view_track_names( - theme, self.tracks_with_sizes(), self.tracks().len(), self.scenes().len(), self.selection() - ) + let track_count = self.tracks().len(); + let scene_count = self.scenes().len(); + let selected = self.selection(); + let button = south( + button_3("t", "rack ", format!("{}{track_count}", selected.track() + .map(|track|format!("{track}/")).unwrap_or_default()), false), + button_3("s", "cene ", format!("{}{scene_count}", selected.scene() + .map(|scene|format!("{scene}/")).unwrap_or_default()), false)); + let button_2 = south( + button_2("T", "+", false), + button_2("S", "+", false)); + view_track_row_section(theme, button, button_2, bg(theme.darker.term, + draw(|to: &mut Tui|{ + for (index, track, x1, _x2) in self.tracks_with_sizes() { + let b = if selected.track() == Some(index) { + track.color.light.term + } else { + track.color.base.term + }; + bg(b, south(east( + format!("·t{index:02} "), + fg(Rgb(255, 255, 255), bold(true, &track.name)) + ).align_nw().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))) } /// Draw outputs per track fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Draw { - view_track_outputs( - theme, self.tracks_with_sizes(), self.midi_outs().iter() - ) + view_track_row_section(theme, + south(button_2("o", "utput", false).align_w().full_w(), + draw(|to: &mut Tui|{ + for port in self.midi_outs().iter() { + let _ = port.port_name().align_w().full_w().draw(to)?; + } + Ok(Some(XYWH(0, 0, 0, 0))) + })), + button_2("O", "+", false), + bg(theme.darker.term, draw(|to: &mut Tui|{ + for (index, track, _x1, _x2) in self.tracks_with_sizes() { + let f = Rgb(255, 255, 255); + let b = track.color.dark.term; + let iter = ||track.sequencer.midi_outs.iter(); + let draw = |port: &MidiOutput, _|fg(f, bg(b, + format!("·o{index:02} {}", port.port_name()).full_w().align_w()).exact_h(1)); + iter_south(iter, draw).full_h().align_nw() + .exact_w(track_width(index, track)) + .draw(to)?; + } + Ok(Some(XYWH(0, 0, 0, 0))) + }).align_w())) } /// Draw inputs per track fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw { - let mut h = 0u16; + let mut height = 0u16; for track in self.tracks().iter() { - h = h.max(track.sequencer.midi_ins.len() as u16); + height = height.max(track.sequencer.midi_ins.len() as u16); } - view_track_inputs(theme, self.tracks_with_sizes(), h) + view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false), + bg(theme.darker.term, draw(move|to: &mut Tui|{ + for (index, track, _x1, _x2) in self.tracks_with_sizes() { + south( + bg(track.color.base.term, + 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 "), + ).align_w().full_w()), + iter_south(||track.sequencer.midi_ins.iter(), + |port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term, + format!("·i{index:02} {}", port.port_name()).align_w().full_w())) + ).align_nw().exact_wh(track_width(index, track), height + 1).draw(to)?; + } + Ok(Some(XYWH(0, 0, 0, 0))) + }).align_w())) } /// Iterate over tracks with their corresponding sizes. fn tracks_with_sizes (&self) -> impl TracksSizes<'_> { @@ -801,21 +870,102 @@ impl_as_mut!(Vec: |self: App| self.project.as_mut()); impl Arrangement { pub fn view_inputs (&self, _theme: ItemTheme) -> impl Draw + '_ { - view_inputs( - self.tracks_with_sizes(), self.midi_ins().as_slice() - ) + let title_1 = button_3("i", "nput ", format!("{}", self.midi_ins().len()), false).align_w().exact_wh(20, 1); + let title_2 = button_2("I", "+", false).exact_wh(4, 1); + east(title_1, west(title_2, draw(move|to: &mut Tui|{ + for (_index, track, x1, _x2) in self.tracks_with_sizes() { + let _ = south( + bg(track.color.dark.term, 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)).align_w().push_x(x1 as u16), + draw(move |to: &mut Tui|{ + for (index, port) in self.midi_ins().as_slice().iter().enumerate() { + let _ = east( + east( + " ● ", + bold(true, fg(Rgb(255,255,255), port.port_name())) + ).align_w().exact_w(20), + west( + ().exact_w(4), + bg(track.color.darker.term, 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).align_w()) + ) + ).push_x(index as u16 * 10).exact_h(1).draw(to)?; + } + todo!() + }) + ).draw(to)?; + } + Ok(Some(to.area())) + }))) } pub fn view_outputs (&self, theme: ItemTheme) -> impl Draw { - view_outputs( - theme, self.tracks_with_sizes(), self.midi_outs(), self.outputs_height() - ) + let height = self.outputs_height(); + let list = south( + button_3( + "o", "utput", format!("{}", self.midi_outs().len()), false + ).align_w().full_w().exact_h(1), + draw(|to: &mut Tui|{ + for (_index, port) in self.midi_outs().iter().enumerate() { + east( + east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))).align_w(), + format!("{}/{} ", + port.port().get_connections().len(), + port.connections.len()).align_e().full_w().exact_h(1)).full_w().draw(to)?; + for (index, conn) in port.connections.iter().enumerate() { + format!(" c{index:02}{}", conn.info()).align_w().full_w().exact_h(1).draw(to)?; + } + } + todo!(); + }).align_nw().full_wh().exact_h(height - 1) + ); + view_track_row_section(theme, list, button_2("O", "+", false), + bg(theme.darker.term, draw(|to: &mut Tui|{ + for (index, track, _x1, _x2) in self.tracks_with_sizes() { + let _ = draw(|to: &mut Tui|{ + east( + either(true, fg(Green, "play "), "play "), + either(false, fg(Yellow, "solo "), "solo "), + ).align_w().exact_h(1).draw(to)?; + for (_index, port) in self.midi_outs().iter().enumerate() { + east( + either(true, fg(Green, " ● "), " · "), + either(false, fg(Yellow, " ● "), " · "), + ).align_w().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!() + }).align_w().full_w())).exact_h(height) } pub fn view_track_devices (&self, theme: ItemTheme) -> impl Draw { - view_track_devices( - theme, self.tracks_with_sizes(), self.track(), self.devices_height() - ) + let height = self.devices_height(); + view_track_row_section(theme, + button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false), + button_2("D", "+", false), + iter_once(self.tracks_with_sizes(), move|(_, track, _x1, _x2), index|bg( + track.color.dark.term, + iter_south(move||0..height, + |_, _index|fg_bg( + ItemTheme::G[32].lightest.term, + ItemTheme::G[32].dark.term, + format!(" · {}", "--").align_nw() + ).exact_wh(track.width as u16, 2) + ).align_nw()).exact_wh( + Some(track_width(index, track)), + Some(height + 1), + ))) } fn devices_height (&self) -> u16 { @@ -898,3 +1048,15 @@ impl HasTrackScroll for App { pub(crate) fn track_width (_index: usize, track: &Track) -> u16 { track.width as u16 } + +/// Define a type alias for iterators of sized items (columns). +macro_rules! def_sizes_iter { + ($Type:ident => $($Item:ty),+) => { + pub trait $Type<'a>: Iterator + Send + Sync + 'a {} + impl<'a, T: Iterator + Send + Sync + 'a> $Type<'a> for T {} + } +} + +def_sizes_iter!(PortsSizes => Arc, [Connect]); +def_sizes_iter!(ScenesSizes => Scene); +def_sizes_iter!(TracksSizes => Track); diff --git a/src/device/editor/piano.rs b/src/device/editor/piano.rs index f4a7b67d..7b2a62de 100644 --- a/src/device/editor/piano.rs +++ b/src/device/editor/piano.rs @@ -144,19 +144,21 @@ impl PianoHorizontal { //if h as usize != note_axis { //panic!("area height mismatch: {h} <> {note_axis}"); //} - for (area_x, screen_x) in (x0..x0+w).enumerate() { - for (area_y, screen_y, _note) in note_y_iter(note_lo, note_hi, y0) { - let source_x = time_start + area_x; - let source_y = note_hi - area_y; - // TODO: enable loop rollover: - //let source_x = (time_start + area_x) % source.width.max(1); - //let source_y = (note_hi - area_y) % source.height.max(1); - let is_in_x = source_x < source.width; - let is_in_y = source_y < source.height; - if is_in_x && is_in_y { - if let Some(source_cell) = source.get(source_x, source_y) { - if let Some(cell) = to.0.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) { - *cell = source_cell.clone(); + if let Tui::Draw(to, ..) = to { + for (area_x, screen_x) in (x0..x0+w).enumerate() { + for (area_y, screen_y, _note) in note_y_iter(note_lo, note_hi, y0) { + let source_x = time_start + area_x; + let source_y = note_hi - area_y; + // TODO: enable loop rollover: + //let source_x = (time_start + area_x) % source.width.max(1); + //let source_y = (note_hi - area_y) % source.height.max(1); + let is_in_x = source_x < source.width; + let is_in_y = source_y < source.height; + if is_in_x && is_in_y { + if let Some(source_cell) = source.get(source_x, source_y) { + if let Some(cell) = to.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) { + *cell = source_cell.clone(); + } } } } diff --git a/src/device/sampler.rs b/src/device/sampler.rs index 681f957e..6e8fa0a8 100644 --- a/src/device/sampler.rs +++ b/src/device/sampler.rs @@ -279,35 +279,39 @@ fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_ lines.push(Line::new(x, min_db, x, y, Color::Green)); t += step / 2.; } - Canvas::default() - .x_bounds([sample.start as f64, sample.end as f64]) - .y_bounds([min_db, 0.]) - .paint(|ctx| { - for line in lines.iter() { - ctx.draw(line); - } - //FIXME: proportions - //let text = "press record to finish sampling"; - //ctx.print( - //(width - text.len() as u16) as f64 / 2.0, - //height as f64 / 2.0, - //text.red() - //); - }) - .render(area, to.as_mut()); + if let Tui::Draw(buf, ..) = to { + Canvas::default() + .x_bounds([sample.start as f64, sample.end as f64]) + .y_bounds([min_db, 0.]) + .paint(|ctx| { + for line in lines.iter() { + ctx.draw(line); + } + //FIXME: proportions + //let text = "press record to finish sampling"; + //ctx.print( + //(width - text.len() as u16) as f64 / 2.0, + //height as f64 / 2.0, + //text.red() + //); + }) + .render(area, buf); + } } else { - Canvas::default() - .x_bounds([0.0, width as f64]) - .y_bounds([0.0, height as f64]) - .paint(|_ctx| { - //let text = "press record to begin sampling"; - //ctx.print( - //(width - text.len() as u16) as f64 / 2.0, - //height as f64 / 2.0, - //text.red() - //); - }) - .render(area, to.as_mut()); + if let Tui::Draw(buf, ..) = to { + Canvas::default() + .x_bounds([0.0, width as f64]) + .y_bounds([0.0, height as f64]) + .paint(|_ctx| { + //let text = "press record to begin sampling"; + //ctx.print( + //(width - text.len() as u16) as f64 / 2.0, + //height as f64 / 2.0, + //text.red() + //); + }) + .render(area, buf); + } } Ok(Some(xywh)) }) diff --git a/src/tek.rs b/src/tek.rs index c7640013..5fd9b660 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -1479,76 +1479,49 @@ mod draw { impl Keywords> for App { fn keywords () -> impl Iterator Perhaps>> { - [ - kw_when, kw_either, kw_split, kw_align, - kw_exact, kw_fixed, kw_min, kw_max, kw_push - ].into_iter() + [kw_when, kw_either, kw_split, kw_align, kw_exact, kw_min, kw_max, kw_push, + kw_tui_text, kw_tui_fg, kw_tui_bg] + .into_iter() } } impl Interpret>> for App { fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn { - tek_draw_expr(self, to, lang) + self.keyword(to, lang) } fn interpret_word <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn { - tek_draw_word(self, to, lang) - } - } - - fn tek_draw_expr (state: &App, to: &mut Tui, lang: &impl Expression) -> Drawn { - Ok(Some(if let Some(area) = eval_view(state, to, lang)? { - area - } else if let Some(area) = Tui::eval_view(state, to, lang)? { - area - } else { - return Err(format!("App::interpret_expr: unexpected: {lang:?}").into()) - })) - } - - fn tek_draw_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Drawn { - let mut frags = dsl.src()?.unwrap().split("/"); - match frags.next() { - //Some(":logo") => view_logo().draw(to), - Some(":meters") => draw_meter_section(to, frags), - Some(":tracks") => draw_tracks(to, frags, state), - Some(":scenes") => draw_scenes(to, frags), - Some(":dialog") => draw_dialog(to, frags, state, dsl), - Some(":templates") => draw_templates(to, frags, state), - Some(":sessions") => view_sessions().draw(to), - Some(":browse/title") => view_browse_title(state).draw(to), - Some(":device") => view_device(state).draw(to), - Some(":status") => "TODO: Status Bar".exact_h(1).draw(to), - Some(":editor") => "TODO Editor".draw(to), - Some(":transport") => view_transport(true, "", "", "").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()) { - let dsl = dsl.clone(); - std::mem::drop(views); - state.interpret(to, &dsl) - } else { - unimplemented!("{dsl:?}"); - } - }, - _ => unreachable!() + let mut frags = lang.src()?.unwrap().split("/"); + match frags.next() { + //Some(":logo") => view_logo().draw(to), + Some(":meters") => draw_meter_section(to, frags), + Some(":tracks") => draw_tracks(to, frags, self), + Some(":scenes") => draw_scenes(to, frags), + Some(":dialog") => draw_dialog(to, frags, self, lang), + Some(":templates") => draw_templates(to, frags, self), + Some(":sessions") => view_sessions().draw(to), + Some(":browse/title") => view_browse_title(self).draw(to), + Some(":device") => view_device(self).draw(to), + Some(":status") => "TODO: Status Bar".exact_h(1).draw(to), + Some(":editor") => "TODO Editor".draw(to), + Some(":transport") => view_transport(true, "", "", "").draw(to), + Some(":debug") => format!("[{:?}]", to.area()).exact_h(1).draw(to), + Some(_) => { + let views = self.config.views.read().unwrap(); + if let Some(lang) = views.get(lang.src()?.unwrap()) { + let lang = lang.clone(); + std::mem::drop(views); + self.interpret(to, &lang) + } else { + unimplemented!("{lang:?}"); + } + }, + _ => unreachable!() + } } } impl_has!(Sizer: |self: App|self.size); - /// Define a type alias for iterators of sized items (columns). - macro_rules! def_sizes_iter { - ($Type:ident => $($Item:ty),+) => { - pub trait $Type<'a>: Iterator + Send + Sync + 'a {} - impl<'a, T: Iterator + Send + Sync + 'a> $Type<'a> for T {} - } - } - - def_sizes_iter!(PortsSizes => Arc, [Connect]); - def_sizes_iter!(ScenesSizes => Scene); - def_sizes_iter!(TracksSizes => Track); - pub trait HasWidth { const MIN_WIDTH: usize; /// Increment track width. @@ -1967,106 +1940,6 @@ mod draw { } } - pub fn view_track_names <'a> ( - theme: ItemTheme, - tracks: impl TracksSizes<'a>, - track_count: usize, - scene_count: usize, - selected: &Selection, - ) -> impl Draw { - let button = south( - button_3("t", "rack ", format!("{}{track_count}", selected.track() - .map(|track|format!("{track}/")).unwrap_or_default()), false), - button_3("s", "cene ", format!("{}{scene_count}", selected.scene() - .map(|scene|format!("{scene}/")).unwrap_or_default()), false)); - let button_2 = south( - button_2("T", "+", false), - button_2("S", "+", false)); - view_track_row_section(theme, button, button_2, bg(theme.darker.term, - draw(|to: &mut Tui|{ - for (index, track, x1, _x2) in tracks { - let b = if selected.track() == Some(index) { - track.color.light.term - } else { - track.color.base.term - }; - bg(b, south(east( - format!("·t{index:02} "), - fg(Rgb(255, 255, 255), bold(true, &track.name)) - ).align_nw().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 <'a> ( - theme: ItemTheme, - tracks: impl TracksSizes<'a>, - midi_outs: impl Iterator, - ) -> impl Draw { - view_track_row_section(theme, - south(button_2("o", "utput", false).align_w().full_w(), - draw(|to: &mut Tui|{ - for port in midi_outs { - let _ = port.port_name().align_w().full_w().draw(to)?; - } - Ok(Some(XYWH(0, 0, 0, 0))) - })), - button_2("O", "+", false), - bg(theme.darker.term, draw(|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(f, bg(b, - format!("·o{index:02} {}", port.port_name()).full_w().align_w()).exact_h(1)); - iter_south(iter, draw).full_h().align_nw() - .exact_w(track_width(index, track)) - .draw(to)?; - } - Ok(Some(XYWH(0, 0, 0, 0))) - }).align_w())) - } - - pub fn view_track_inputs <'a> ( - theme: ItemTheme, tracks: impl TracksSizes<'a>, height: u16, - ) -> impl Draw { - view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false), - bg(theme.darker.term, draw(move|to: &mut Tui|{ - for (index, track, _x1, _x2) in tracks { - south( - bg(track.color.base.term, - 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 "), - ).align_w().full_w()), - iter_south(||track.sequencer.midi_ins.iter(), - |port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term, - format!("·i{index:02} {}", port.port_name()).align_w().full_w())) - ).align_nw().exact_wh(track_width(index, track), height + 1).draw(to)?; - } - Ok(Some(XYWH(0, 0, 0, 0))) - }).align_w())) - } - - pub fn view_scenes_names <'a> ( - scenes: impl ScenesSizes<'a>, - select: &Selection, - editor: Option<&MidiEditor>, - editing: bool, - ) -> impl Draw { - draw(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 ( select: &Selection, editor: Option<&MidiEditor>, @@ -2121,119 +1994,4 @@ mod draw { }) } - pub fn view_per_track () -> impl Draw {} - - pub fn view_per_track_top () -> impl Draw {} - - pub fn view_inputs <'a> ( - tracks: impl TracksSizes<'a>, midi_ins: &[MidiInput] - ) -> impl Draw { - let title_1 = button_3("i", "nput ", format!("{}", midi_ins.len()), false).align_w().exact_wh(20, 1); - let title_2 = button_2("I", "+", false).exact_wh(4, 1); - east(title_1, west(title_2, draw(move|to: &mut Tui|{ - for (_index, track, x1, _x2) in tracks { - let _ = south( - bg(track.color.dark.term, 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)).align_w().push_x(x1 as u16), - draw(move |to: &mut Tui|{ - for (index, port) in midi_ins.iter().enumerate() { - let _ = east( - east( - " ● ", - bold(true, fg(Rgb(255,255,255), port.port_name())) - ).align_w().exact_w(20), - west( - ().exact_w(4), - bg(track.color.darker.term, 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).align_w()) - ) - ).push_x(index as u16 * 10).exact_h(1).draw(to)?; - } - todo!() - }) - ).draw(to)?; - } - todo!() - }))) - } - - pub fn view_outputs <'a> ( - theme: ItemTheme, - tracks: impl TracksSizes<'a>, - midi_outs: &[MidiOutput], - height: u16, - ) -> impl Draw { - - let list = south( - button_3( - "o", "utput", format!("{}", midi_outs.len()), false - ).align_w().full_w().exact_h(1), - draw(|to: &mut Tui|{ - for (_index, port) in midi_outs.iter().enumerate() { - east( - east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))).align_w(), - format!("{}/{} ", - port.port().get_connections().len(), - port.connections.len()).align_e().full_w().exact_h(1)).full_w().draw(to)?; - for (index, conn) in port.connections.iter().enumerate() { - format!(" c{index:02}{}", conn.info()).align_w().full_w().exact_h(1).draw(to)?; - } - } - todo!(); - }).align_nw().full_wh().exact_h(height - 1) - ); - - view_track_row_section(theme, list, button_2("O", "+", false), - bg(theme.darker.term, draw(|to: &mut Tui|{ - for (index, track, _x1, _x2) in tracks { - let _ = draw(|to: &mut Tui|{ - east( - either(true, fg(Green, "play "), "play "), - either(false, fg(Yellow, "solo "), "solo "), - ).align_w().exact_h(1).draw(to)?; - for (_index, port) in midi_outs.iter().enumerate() { - east( - either(true, fg(Green, " ● "), " · "), - either(false, fg(Yellow, " ● "), " · "), - ).align_w().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!() - }).align_w().full_w())).exact_h(height) - } - - pub fn view_track_devices <'a> ( - theme: ItemTheme, - tracks: impl TracksSizes<'a>, - track: Option<&Track>, - h: u16, - ) -> impl Draw { - 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|bg( - track.color.dark.term, - iter_south(move||0..h, - |_, _index|fg_bg( - ItemTheme::G[32].lightest.term, - ItemTheme::G[32].dark.term, - format!(" · {}", "--").align_nw() - ).exact_wh(track.width as u16, 2) - ).align_nw()).exact_wh( - Some(track_width(index, track)), - Some(h + 1), - ))) - } - } diff --git a/tengri b/tengri index eb028c85..ac9fd7df 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit eb028c85fc94a1b86c44d4f079e5fb91667d4db2 +Subproject commit ac9fd7dfba24335d09793a55d94ea54039253f62