diff --git a/config/config_arranger.edn b/config/config_arranger.edn index 7fb8416f..7971cd41 100644 --- a/config/config_arranger.edn +++ b/config/config_arranger.edn @@ -26,6 +26,6 @@ (fill/xy (align/n (bsp/s :view-arranger-track-names (bsp/s :view-arranger-track-outputs (bsp/s :view-arranger-track-devices :view-arranger-track-inputs))))))) - (bsp/w - (fixed/x 20 :view-pool) - :view-arranger-scenes))) + (fill/xy (align/w (bsp/e + (fill/y (align/n (fixed/x 20 :view-arranger-scenes-names))) + (fill/y (align/n :view-arranger-scenes-clips))))))))) diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index 9696e698..1138f078 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -195,6 +195,9 @@ impl App { fn focus_editor (&self) -> bool { self.is_editing() } + fn is_editing (&self) -> bool { + HasEditor::is_editing(self) + } fn focus_message (&self) -> bool { matches!(self.dialog, Some(Dialog::Message(..))) } diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index a84c9bb6..d5723f74 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -107,6 +107,12 @@ impl App { pub fn view_arranger_scenes (&self) -> impl Content + use<'_> { self.scenes_view(&self.editor) } + pub fn view_arranger_scenes_names (&self) -> impl Content + use<'_> { + self.scenes_names() + } + pub fn view_arranger_scenes_clips (&self) -> impl Content + use<'_> { + self.scenes_clips(&self.editor) + } pub fn view_arranger_scene_names <'a> (&'a self) -> impl Content + use<'a> { let h = self.project.scenes.len() as u16 * 2; let bg = self.color.darker.rgb; @@ -357,16 +363,16 @@ impl App { impl ArrangerSceneRows for App { fn arrangement (&self) -> &Arrangement { - self.project + &self.project } fn scenes_height (&self) -> u16 { - self.project.scenes_height + (self.height() as u16).saturating_sub(20) } - fn width_side (&self) -> u16 { + fn width_side (&self) -> u16 { 20 } - fn width_mid (&self) -> u16 { - self.width().saturating_sub(self.width_side() * 2) + fn width_mid (&self) -> u16 { + (self.width() as u16).saturating_sub(self.width_side()) } fn scene_selected (&self) -> Option { self.project.selection.scene() @@ -378,7 +384,7 @@ impl ArrangerSceneRows for App { self.project.selection.track() } fn is_editing (&self) -> bool { - self.is_editing + self.editor.is_some() } } diff --git a/crates/device/src/arranger/arranger_scenes.rs b/crates/device/src/arranger/arranger_scenes.rs index 941b99ba..f14d686f 100644 --- a/crates/device/src/arranger/arranger_scenes.rs +++ b/crates/device/src/arranger/arranger_scenes.rs @@ -22,7 +22,8 @@ pub trait ArrangerSceneRows: Send + Sync { fn width_side (&self) -> u16; fn width_mid (&self) -> u16; fn scenes_names (&self) -> impl Content { - Map::new(move||self.scenes_with_prev_color(), + let h = self.scenes_with_prev_color().last().map(|(_,_,_,h,_)|h as u16).unwrap_or(0); + Fixed::y(h, Map::new(move||self.scenes_with_prev_color(), move|(s, scene, y1, y2, previous): SceneWith<'_, Option>, _|{ let height = (1 + y2 - y1) as u16; let name = Some(scene.name.clone()); @@ -46,16 +47,25 @@ pub trait ArrangerSceneRows: Send + Sync { Fill::x(map_south(y1 as u16, height, Fixed::y(height, Phat { width: 0, height: 0, content, colors: [fg, bg, hi, lo] }))) - }) + })) } fn scenes_with_prev_color (&self) -> impl Iterator>> + Send + Sync { self.scenes_iter().map(|(s, scene, y1, y2)|(s, scene, y1, y2, - (s>0).then_some(self.arrangement().scenes()[s-1].color))) + (s>0).then(||self.arrangement().scenes()[s-1].color))) + } + fn per_track <'a, T: Content + 'a, U: TracksSizes<'a>> ( + tracks: impl Fn() -> U + Send + Sync + 'a, + callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a + ) -> impl Content + 'a { + Map::new(tracks, move|(index, track, x1, x2): (usize, &'a Track, usize, usize), _|{ + Tui::fg_bg(track.color.lightest.rgb, track.color.darker.rgb, + map_east(x1 as u16, (x2 - x1) as u16, callback(index, track))) }) } fn scenes_clips <'a> (&'a self, editor: &'a Option) -> impl Content + 'a { - per_track(||self.tracks_with_sizes_scrolled(), + let h = self.scenes_with_prev_color().last().map(|(_,_,_,h,_)|h as u16).unwrap_or(0); + Fixed::y(h, Self::per_track(||self.tracks_with_sizes_scrolled(), move|track_index, track|Map::new(move||self.scenes_with_clip(track_index), move|(s, scene, y1, y2, previous): SceneWith<'_, Option>, _|{ let (name, theme) = if let Some(clip) = &scene.clips[track_index] { @@ -64,7 +74,6 @@ pub trait ArrangerSceneRows: Send + Sync { } else { (None, ItemTheme::G[32]) }; - let height = (1 + y2 - y1) as u16; let content = Fill::x(Align::w(Tui::bold(true, Bsp::e(" ⏹ ", name)))); let same_track = self.track_selected() == Some(track_index); let selected = same_track && self.scene_selected() == Some(s); @@ -73,11 +82,7 @@ pub trait ArrangerSceneRows: Send + Sync { let fg = theme.lightest.rgb; let bg = if selected { theme.light } else { theme.base }.rgb; let hi = if let Some(previous) = previous { - if neighbor { - previous.light.rgb - } else { - previous.base.rgb - } + if neighbor { previous.light.rgb } else { previous.base.rgb } } else { Reset }; @@ -88,17 +93,18 @@ pub trait ArrangerSceneRows: Send + Sync { } else { theme.base.rgb }; + let height = (1 + y2 - y1) as u16; map_south(y1 as u16, height, Bsp::b(Fixed::y(height, Phat { width: 0, height: 0, content, colors: [fg, bg, hi, lo] }), When( self.is_editing() && same_track && self.scene_selected() == Some(s), editor ))) - })) + }))) } fn scenes_with_clip (&self, track_index: usize) -> impl Iterator>> + Send + Sync { self.scenes_iter().map(move|(s, scene, y1, y2)|(s, scene, y1, y2, - (s>0).then_some(self.arrangement().scenes()[s-1].clips[track_index].as_ref() + (s>0).then(||self.arrangement().scenes()[s-1].clips[track_index].as_ref() .map(|c|c.read().unwrap().color) .unwrap_or(ItemTheme::G[32])))) } diff --git a/crates/device/src/editor/editor_model.rs b/crates/device/src/editor/editor_model.rs index c0444a9b..f7495032 100644 --- a/crates/device/src/editor/editor_model.rs +++ b/crates/device/src/editor/editor_model.rs @@ -106,7 +106,7 @@ impl MidiViewer for MidiEditor { pub trait HasEditor { fn editor (&self) -> Option<&MidiEditor>; fn editor_mut (&mut self) -> Option<&mut MidiEditor>; - fn is_editing (&self) -> bool { true } + fn is_editing (&self) -> bool { self.editor().is_some() } fn editor_w (&self) -> usize { 0 } fn editor_h (&self) -> usize { 0 } } diff --git a/deps/tengri b/deps/tengri index c954965a..4ff4ea81 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit c954965ae125136286291e5f0d4532edf98f46ad +Subproject commit 4ff4ea81735548f808302c61b619ad7804e1eec0