diff --git a/config/config_arranger.edn b/config/config_arranger.edn index 88191575..828b549d 100644 --- a/config/config_arranger.edn +++ b/config/config_arranger.edn @@ -21,8 +21,7 @@ (bsp/a :view-dialog (bsp/w :view-meters-output (bsp/e :view-meters-input - (bsp/s - :view-status-h2 + (bsp/n (fixed/y 2 :view-status-h2) (bsp/n (fill/x (align/w :view-tracks-inputs)) (bsp/s (fill/x (align/w :view-tracks-names)) (bsp/s (fill/x (align/w :view-tracks-outputs)) diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index c0900f5e..e42143d7 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -115,10 +115,10 @@ impl App { ) } pub fn view_tracks_inputs <'a> (&'a self) -> impl Content + use<'a> { - Fixed::y(2, self.project.view_track_inputs(self.color)) + Fixed::y(2 + self.project.midi_ins.len() as u16, self.project.view_inputs(self.color)) } pub fn view_tracks_outputs <'a> (&'a self) -> impl Content + use<'a> { - Fixed::y(1 + self.project.midi_outs.len() as u16, self.project.view_track_outputs(self.color, self.midi_outs().len().min(24) as u16)) + Fixed::y(1 + self.project.midi_outs.len() as u16, self.project.view_outputs(self.color)) } pub fn view_tracks_devices <'a> (&'a self) -> impl Content + use<'a> { Fixed::y(3, self.project.view_track_devices(self.color)) diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index e27773c7..dbf87f2c 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -1,5 +1,67 @@ use crate::*; +impl Arrangement { + pub fn view_inputs <'a> (&'a self, theme: ItemTheme) -> impl Content + 'a { + let mut h = 1u16; + for track in self.tracks().iter() { + h = h.max(track.sequencer.midi_ins.len() as u16); + } + let h = h + 1; + self.view_track_row_section( + theme, + Bsp::s( + Fill::x(Align::w(button_2("i", "nput", false))), + Fill::x(Align::nw(Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ + add(&"kyp"); + for (index, port) in self.midi_ins.iter().enumerate() { + add(&Fill::x(Align::w(format!("·i{index:02} {}", port.name())))); + } + })))), + button_2("I", "+", false), + Tui::bg(theme.darker.rgb, Align::w(Fill::x( + Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ + for (index, track, x1, x2) in self.tracks_with_sizes() { + add(&Fixed::xy(self.track_width(index, track), h, + Align::nw(Bsp::s( + Tui::bg(track.color.base.rgb, + Fill::x(Align::w(row!( + Either(track.sequencer.monitoring, Tui::fg(Green, "●mon "), "·mon "), + Either(track.sequencer.recording, Tui::fg(Red, "●rec "), "·rec "), + Either(track.sequencer.overdub, Tui::fg(Yellow, "●dub "), "·dub "), + )))), + Map::south(1, ||track.sequencer.midi_ins.iter(), + |port, index|Tui::fg_bg(Rgb(255, 255, 255), track.color.dark.rgb, + Fill::x(Align::w(format!("·i{index:02} {}", port.name()))))))))); + }}))))) + } + pub fn view_outputs <'a> (&'a self, theme: ItemTheme) -> impl Content + 'a { + let mut h = 1u16; + for track in self.tracks().iter() { + h = h.max(track.sequencer.midi_outs.len() as u16); + } + let h = h + 1; + self.view_track_row_section( + theme, + Bsp::s(Fill::x(Align::w(button_2("o", "utput", false))), + Fill::xy(Align::nw(Stack::south(|add: &mut dyn FnMut(&dyn Render)|{ + for (index, port) in self.midi_outs().iter().enumerate() { + add(&Fill::x(Align::w(format!("·o{index:02} {}", port.name())))); + } + })))), + button_2("O", "+", false), + Tui::bg(theme.darker.rgb, Align::w(Fill::x( + Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ + for (index, track, x1, x2) in self.tracks_with_sizes() { + add(&Fixed::x(self.track_width(index, track), + Align::nw(Fill::y(Map::south(1, ||track.sequencer.midi_outs.iter(), + |port, index|Tui::fg(Rgb(255, 255, 255), + Fixed::y(1, Tui::bg(track.color.dark.rgb, Fill::x(Align::w( + format!("·o{index:02} {}", port.name()))))))))))); + } + }))))) + } +} + pub trait HasClipsSize { fn clips_size (&self) -> &Measure; } @@ -30,8 +92,8 @@ pub trait TracksView: let active_track = self.selection().track(); let mut x = 0; self.tracks().iter().enumerate().map_while(move |(index, track)|{ - if x < self.clips_size().w() { - let width = active_track.and_then(|_|editor_width).unwrap_or(track.width.max(8)); + let width = active_track.and_then(|_|editor_width).unwrap_or(track.width.max(8)); + if x + width < self.clips_size().w() { let data = (index, track, x, x + width); x += width + Self::TRACK_SPACING; Some(data) @@ -40,13 +102,6 @@ pub trait TracksView: } }) } - fn tracks_with_sizes_scrolled <'t> (&'t self) -> impl TracksSizes<'t> { - self.tracks_with_sizes() - .skip(self.track_scroll()) - .map_while(move|(t, track, x1, x2)| - ((x2 as u16) < self.tracks_width_available()) - .then_some((t, track, x1, x2))) - } fn view_track_row_section <'a> ( &'a self, theme: ItemTheme, @@ -97,7 +152,7 @@ pub trait TracksView: Fill::x(Align::w(button_2("o", "utput", false))), Fill::xy(Stack::south(|add: &mut dyn FnMut(&dyn Render)|{ for port in self.midi_outs().iter() { - add(&Push::x(2, Fill::x(Align::w(port.name())))); + add(&Fill::x(Align::w(port.name()))); } }))), button_2("O", "+", false), @@ -189,10 +244,10 @@ pub trait ScenesView: let selected_scene = self.selection().scene(); let mut y = 0; self.scenes().iter().enumerate().skip(self.scene_scroll()).map_while(move|(s, scene)|{ - if y < self.clips_size().h() { - let active = editing && selected_track.is_some() && selected_scene == Some(s); - let height = if active { larger } else { height }; - let data = (s, scene, y, y + height); + let active = editing && selected_track.is_some() && selected_scene == Some(s); + let height = if active { larger } else { height }; + if y + height < self.clips_size().h() { + let data = (s, scene, y, y + height); y += height; Some(data) } else {