From 9fcb5a08c6aba9c0c00ed47801f61360a7e59982 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 17 May 2025 21:50:14 +0300 Subject: [PATCH 1/5] style editor stats as commands --- crates/device/src/arranger/arranger_api.rs | 8 ++ crates/device/src/arranger/arranger_view.rs | 87 ++++++++------------- crates/device/src/editor/editor_view.rs | 27 +++++-- 3 files changed, 60 insertions(+), 62 deletions(-) diff --git a/crates/device/src/arranger/arranger_api.rs b/crates/device/src/arranger/arranger_api.rs index 46043485..07377856 100644 --- a/crates/device/src/arranger/arranger_api.rs +++ b/crates/device/src/arranger/arranger_api.rs @@ -39,6 +39,14 @@ impl ArrangementCommand { } } }; + if let Some(editor) = arranger.editor.as_mut() { + if let Some(clip) = editor.clip() { + let length = clip.read().unwrap().length.max(1); + let width = arranger.inner_size.w().saturating_sub(20).max(1); + editor.set_time_zoom(length / width); + editor.redraw(); + } + } Ok(None) } /// Set the selection diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index 55cc5198..07795750 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -2,21 +2,19 @@ use crate::*; impl Arrangement { pub fn view_inputs <'a> (&'a self, theme: ItemTheme) -> impl Content + 'a { - let mut h = 0; + let mut h = 1u16; for track in self.tracks().iter() { h = h.max(self.midi_ins.len() as u16); } let h = h + 1; - self.view_track_row_section( - theme, - Bsp::s( - Fixed::y(1, Fill::x(Align::w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false)))), - Fixed::y(h - 1, Fill::x(Align::nw(Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ - for (index, port) in self.midi_ins.iter().enumerate() { - add(&Fill::x(Align::w(format!("·i{index:02} {}", port.name())))); - } - }))))), - button_2("I", "+", false), + let list = Bsp::s( + Fixed::y(1, Fill::x(Align::w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false)))), + Fixed::y(h - 1, Fill::x(Align::nw(Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ + for (index, port) in self.midi_ins.iter().enumerate() { + add(&Fill::x(Align::w(format!("·i{index:02} {}", port.name())))); + } + }))))); + self.view_track_row_section(theme, list, 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() { @@ -41,16 +39,14 @@ impl Arrangement { h = h.max(track.sequencer.midi_outs.len() as u16); } let h = h + 1; - self.view_track_row_section( - theme, - Bsp::s( - Fixed::y(1, Fill::x(Align::w(button_3("o", "utput", format!("{}", self.midi_outs.len()), false)))), - Fixed::y(h - 1, 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), + let list = Bsp::s( + Fixed::y(1, Fill::x(Align::w(button_3("o", "utput", format!("{}", self.midi_outs.len()), false)))), + Fixed::y(h - 1, 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())))); + } + }))))); + self.view_track_row_section(theme, list, 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() { @@ -64,11 +60,10 @@ impl Arrangement { add(&Fixed::y(1, Align::w(Bsp::e( Either(true, Tui::fg(Green, "●play "), "·play "), Either(false, Tui::fg(Yellow, "●solo "), "·solo "), + )))); } - }))); - } - }))))) + })))}}))))) } pub fn view_track_devices <'a> (&'a self, theme: ItemTheme) -> impl Content + 'a { let mut h = 2u16; @@ -79,14 +74,13 @@ impl Arrangement { theme, button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false), button_2("D", "+", false), - Fixed::y(h, 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 + 1, - Tui::bg(track.color.dark.rgb, Align::nw(Map::south(1, move||0..h, - |_, index|format!("·d{index:02} {}", "--------")))))); - } - })))))) + 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 + 1, + Tui::bg(track.color.dark.rgb, Align::nw(Map::south(1, move||0..h, + |_, index|format!("·d{index:02} {}", "--------")))))); + } + })) } } @@ -137,13 +131,8 @@ pub trait TracksView: button_add: impl Content, content: impl Content ) -> impl Content { - Bsp::w( - Fill::y(Fixed::x(4, Align::nw(button_add))), - Bsp::e( - Fixed::x(20, Fill::y(Align::nw(button))), - Fill::xy(Align::c(content)) - ) - ) + Bsp::w(Fill::y(Fixed::x(4, Align::nw(button_add))), + Bsp::e(Fixed::x(20, Fill::y(Align::nw(button))), Fill::xy(Align::c(content)))) } fn view_track_header <'a, T: Content> ( &'a self, theme: ItemTheme, content: T @@ -231,13 +220,7 @@ pub trait TracksView: }}))))) } fn track_width (&self, index: usize, track: &Track) -> u16 { - (if self.selection().track() == Some(index) - && let Some(editor) = self.editor() - { - editor.width().max(24).max(track.width) - } else { - track.width - }) as u16 + track.width as u16 } } @@ -264,8 +247,6 @@ 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)|{ - 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; @@ -284,7 +265,7 @@ pub trait ScenesView: } fn view_scene_name (&self, index: usize, scene: &Scene) -> impl Content { let h = if self.selection().scene() == Some(index) && let Some(editor) = self.editor() { - (editor.height() as u16).max(12) + 7 } else { Self::H_SCENE as u16 }; @@ -321,13 +302,7 @@ pub trait ClipsView: for (track_index, track, _, _) in self.tracks_with_sizes() { //column(&Fixed::x(5, Fill::xy(Tui::bg(Green, "kyp")))); column(&Fixed::x( - if self.selection().track() == Some(track_index) - && let Some(editor) = self.editor() - { - editor.width().max(24).max(track.width) - } else { - track.width - } as u16, + track.width as u16, Fill::y(self.view_track_clips(track_index, track)) )) } diff --git a/crates/device/src/editor/editor_view.rs b/crates/device/src/editor/editor_view.rs index 7e0c9661..c553cdfc 100644 --- a/crates/device/src/editor/editor_view.rs +++ b/crates/device/src/editor/editor_view.rs @@ -13,9 +13,15 @@ impl MidiEditor { (clip.color, clip.name.clone(), clip.length, clip.looped) } else { (ItemTheme::G[64], String::new().into(), 0, false) }; Fixed::x(20, col!( - Fill::x(Align::w(Bsp::e(" Clip ", format!("{name}")))), - Fill::x(Align::w(Bsp::e(" Length ", format!("{length}")))), - Fill::x(Align::w(Bsp::e(" Loop ", looped.to_string()))), + Fill::x(Align::w(Bsp::e( + button_2("f2", "name ", false), + Fill::x(Align::e(Tui::fg(Rgb(255, 255, 255), format!("{name} "))))))), + Fill::x(Align::w(Bsp::e( + button_2("l", "ength ", false), + Fill::x(Align::e(Tui::fg(Rgb(255, 255, 255), format!("{length} "))))))), + Fill::x(Align::w(Bsp::e( + button_2("r", "epeat ", false), + Fill::x(Align::e(Tui::fg(Rgb(255, 255, 255), format!("{looped} "))))))), )) } @@ -31,9 +37,18 @@ impl MidiEditor { let note_pos = format!("{:>3}", note_pos); let note_len = format!("{:>4}", self.get_note_len()); Fixed::x(20, col!( - Fill::x(Align::w(Bsp::e(" Time ", format!("{length}/{time_zoom}+{time_pos}")))), - Fill::x(Align::w(Bsp::e(" Lock ", format!("{time_lock}")))), - Fill::x(Align::w(Bsp::e(" Note ", format!("{note_name} {note_pos} {note_len}")))), + Fill::x(Align::w(Bsp::e( + button_2("t", "ime ", false), + Fill::x(Align::e(Tui::fg(Rgb(255, 255, 255), + format!("{length} /{time_zoom} +{time_pos} "))))))), + Fill::x(Align::w(Bsp::e( + button_2("z", "lock ", false), + Fill::x(Align::e(Tui::fg(Rgb(255, 255, 255), + format!("{time_lock}"))))))), + Fill::x(Align::w(Bsp::e( + button_2("x", "note ", false), + Fill::x(Align::e(Tui::fg(Rgb(255, 255, 255), + format!("{note_name} {note_pos} {note_len}"))))))), )) } From 01db41b75d288193bc23881ffc50759536a47017 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 17 May 2025 21:56:46 +0300 Subject: [PATCH 2/5] arranger: trying to fix conditional layers --- config/config_arranger.edn | 10 +++++----- crates/app/src/model.rs | 9 +++++++-- crates/app/src/view.rs | 6 ++++-- crates/device/src/arranger/arranger_view.rs | 14 +++++++------- deps/tengri | 2 +- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/config/config_arranger.edn b/config/config_arranger.edn index a83b8521..8ac29f05 100644 --- a/config/config_arranger.edn +++ b/config/config_arranger.edn @@ -22,10 +22,10 @@ (bsp/w :view-meters-output (bsp/e :view-meters-input (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-devices)) - (bsp/s (fill/x (align/w :view-tracks-outputs)) - (bsp/s (fill/x (align/w :view-tracks-names)) + (bsp/n :view-tracks-inputs + (bsp/s :view-tracks-devices + (bsp/s :view-tracks-outputs + (bsp/s :view-tracks-names (fill/xy (either :is-editing - (bsp/e (fixed/x 20 :view-scenes-names) :view-editor) + (bsp/e :view-scenes-names :view-editor) :view-scenes))))))))))) diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index 5ede40e6..5553da0e 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -435,7 +435,8 @@ impl Configuration { return Err(format!("(e4) unexpected non-symbol {next:?}").into()) }; - if let Some(Token { value: Value::Str(path), .. }) = exp.peek() { + let token = exp.peek(); + if let Some(Token { value: Value::Str(path), .. }) = token { let path = base.as_ref().parent().unwrap().join(unquote(path)); if !std::fs::exists(&path)? { return Err(format!("(e5) not found: {path:?}").into()) @@ -448,7 +449,11 @@ impl Configuration { map.add_layer_if( Box::new(move |state|{ let mut exp = exp.clone(); - Context::get(state, &mut exp).unwrap_or(false) + let value = Context::get(state, &mut format!(":{cond}").as_str().into()).unwrap_or(false); + if value { + panic!("layer-if cond={cond:?} exp={exp:?} value={value:?}"); + } + value }), keys ); diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index 1a67e193..d13c65e1 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -123,10 +123,12 @@ impl App { self.project.view_scenes_clips() } pub fn view_tracks_inputs <'a> (&'a self) -> impl Content + use<'a> { - Fixed::y(1 + self.project.midi_ins.len() as u16, self.project.view_inputs(self.color)) + Fixed::y(1 + 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_outputs(self.color)) + 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 07795750..c4adb55f 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -240,13 +240,13 @@ pub trait ScenesView: fn w_side (&self) -> u16; fn w_mid (&self) -> u16; fn scenes_with_sizes (&self) -> impl ScenesSizes<'_> { - let editing = self.editor().is_some(); - let height = Self::H_SCENE; - let larger = 8;//FIXME//self.editor().map(|e|e.height()).unwrap_or(Self::H_SCENE); - let selected_track = self.selection().track(); - let selected_scene = self.selection().scene(); let mut y = 0; self.scenes().iter().enumerate().skip(self.scene_scroll()).map_while(move|(s, scene)|{ + let height = if self.selection().scene() == Some(s) && self.editor().is_some() { + 8 + } else { + Self::H_SCENE + }; if y + height <= self.clips_size().h() { let data = (s, scene, y, y + height); y += height; @@ -257,11 +257,11 @@ pub trait ScenesView: }) } fn view_scenes_names (&self) -> impl Content { - Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ + Fixed::x(20, Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ for (index, scene, ..) in self.scenes_with_sizes() { add(&self.view_scene_name(index, scene)); } - }) + })) } fn view_scene_name (&self, index: usize, scene: &Scene) -> impl Content { let h = if self.selection().scene() == Some(index) && let Some(editor) = self.editor() { diff --git a/deps/tengri b/deps/tengri index f21781e8..9a12e0c7 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit f21781e81664e1991e3985e2377becca9c1d58cf +Subproject commit 9a12e0c7bab24cb708d503e860d93677ae306961 From 50c263b4d3b37164b21d7d513cbcde38940ee450 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 17 May 2025 22:04:25 +0300 Subject: [PATCH 3/5] fix disappearing input rows --- crates/app/src/view.rs | 2 +- crates/device/src/arranger/arranger_view.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index d13c65e1..c73e6b77 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -131,7 +131,7 @@ impl App { 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)) + Fixed::y(2, self.project.view_track_devices(self.color)) } pub fn view_tracks_names <'a> (&'a self) -> impl Content + use<'a> { Fixed::y(2, self.project.view_track_names(self.color)) diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index c4adb55f..ed299a53 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -7,13 +7,13 @@ impl Arrangement { h = h.max(self.midi_ins.len() as u16); } let h = h + 1; - let list = Bsp::s( - Fixed::y(1, Fill::x(Align::w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false)))), - Fixed::y(h - 1, Fill::x(Align::nw(Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ - for (index, port) in self.midi_ins.iter().enumerate() { - add(&Fill::x(Align::w(format!("·i{index:02} {}", port.name())))); - } - }))))); + let list = Fixed::x(20, Fill::y(Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ + add(&Fixed::y(1, Align::w( + button_3("i", "nput ", format!("{}", self.midi_ins.len()), false)))); + for (index, port) in self.midi_ins.iter().enumerate() { + add(&Fixed::y(1, Fill::x(Align::w(format!("·i{index:02} {}", port.name()))))); + } + }))); self.view_track_row_section(theme, list, button_2("I", "+", false), Tui::bg(theme.darker.rgb, Align::w(Fill::x( Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ From 958e602577b1786c681946f065152163c85e1b5d Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 17 May 2025 23:05:29 +0300 Subject: [PATCH 4/5] use stack in view_inputs --- Justfile | 2 +- crates/app/src/view.rs | 5 +- crates/device/src/arranger/arranger_view.rs | 103 +++++++++++--------- 3 files changed, 61 insertions(+), 49 deletions(-) diff --git a/Justfile b/Justfile index 5ecece41..e91a5c36 100644 --- a/Justfile +++ b/Justfile @@ -64,7 +64,7 @@ arranger-ext: arranger-release: {{release}} {{name}} {{bpm}} arranger arranger-release-ext: - {{release}} {{name}} {{bpm}} {{midi-in}} {{midi-out}} arranger + {{release}} {{name}} {{bpm}} {{midi-in}} {{firefox-in}} {{midi-out}} arranger groovebox: {{debug}} {{name}} {{bpm}} groovebox diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index c73e6b77..dc93ffce 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -127,11 +127,10 @@ impl App { 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_outputs(self.color)) + self.project.view_outputs(self.color) } pub fn view_tracks_devices <'a> (&'a self) -> impl Content + use<'a> { - Fixed::y(2, self.project.view_track_devices(self.color)) + Fixed::y(4, self.project.view_track_devices(self.color)) } pub fn view_tracks_names <'a> (&'a self) -> impl Content + use<'a> { Fixed::y(2, self.project.view_track_names(self.color)) diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index ed299a53..5f45499b 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -7,78 +7,91 @@ impl Arrangement { h = h.max(self.midi_ins.len() as u16); } let h = h + 1; - let list = Fixed::x(20, Fill::y(Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ - add(&Fixed::y(1, Align::w( - button_3("i", "nput ", format!("{}", self.midi_ins.len()), false)))); - for (index, port) in self.midi_ins.iter().enumerate() { - add(&Fixed::y(1, Fill::x(Align::w(format!("·i{index:02} {}", port.name()))))); - } - }))); - self.view_track_row_section(theme, list, 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::x(self.track_width(index, track), - Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ - let index = 0; - add(&Fixed::y(1, track.sequencer.midi_ins.get(0).map(|port| - Tui::fg_bg(Rgb(255, 255, 255), track.color.base.rgb, - Fill::x(Align::w(format!("·i{index:02} {}", port.name()))))))); - for (index, port) in self.midi_ins().iter().enumerate() { - add(&Fixed::y(1, 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 "), - )))); + Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ + add(&Fixed::y(1, + Bsp::e(Fixed::x(20, Align::w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false))), + Bsp::w(Fixed::x(4, button_2("I", "+", false)), + Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ + for (index, track, x1, x2) in self.tracks_with_sizes() { + add(&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 "), + ))) + } + }))))); + for (index, port) in self.midi_ins().iter().enumerate() { + add(&Fixed::y(1, + Bsp::e(Fixed::x(20, Align::w(format!(" ● i{index:02} {}", port.name()))), + Bsp::w(Fixed::x(4, ()), + Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ + for (index, track, x1, x2) in self.tracks_with_sizes() { + add(&Align::w(row!( + Either(track.sequencer.monitoring, Tui::fg(Green, " ● "), " · "), + Either(track.sequencer.recording, Tui::fg(Red, " ● "), " · "), + Either(track.sequencer.overdub, Tui::fg(Yellow, " ● "), " · "), + ))) } - })))}}))))) + }))))); + } + }) } 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 mut h = 1; + for output in self.midi_outs().iter() { + h += 1 + output.conn().len(); } - let h = h + 1; + let h = h as u16; let list = Bsp::s( Fixed::y(1, Fill::x(Align::w(button_3("o", "utput", format!("{}", self.midi_outs.len()), false)))), Fixed::y(h - 1, 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())))); + add(&Fixed::y(1,Fill::x(Bsp::e( + Align::w(Bsp::e(format!(" ● o{index:02} "), Tui::fg(Rgb(255,255,255),Tui::bold(true, port.name())))), + Fill::x(Align::e(format!("{}/{} ", + port.port().get_connections().len(), + port.conn().len()))))))); + for (index, conn) in port.conn().iter().enumerate() { + add(&Fixed::y(1, Fill::x(Align::w(format!(" c{index:02}{}", conn.info()))))); + } } }))))); - self.view_track_row_section(theme, list, button_2("O", "+", false), + Fixed::y(h, self.view_track_row_section(theme, list, 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), Stack::south(move|add: &mut dyn FnMut(&dyn Render)|{ let index = 0; - add(&Fixed::y(1, track.sequencer.midi_outs.get(0).map(|port| - Tui::fg_bg(Rgb(255, 255, 255), track.color.base.rgb, - Fill::x(Align::w(format!("·o{index:02} {}", port.name()))))))); + add(&Fixed::y(1, Align::w(Bsp::e( + Either(true, Tui::fg(Green, "play "), "play "), + Either(false, Tui::fg(Yellow, "solo "), "solo "), + )))); for (index, port) in self.midi_outs().iter().enumerate() { add(&Fixed::y(1, Align::w(Bsp::e( - Either(true, Tui::fg(Green, "●play "), "·play "), - Either(false, Tui::fg(Yellow, "●solo "), "·solo "), - + Either(true, Tui::fg(Green, " ● "), " · "), + Either(false, Tui::fg(Yellow, " ● "), " · "), )))); - } - })))}}))))) + for (index, conn) in port.conn().iter().enumerate() { + add(&Fixed::y(1, Fill::x(""))); + } + }})))}})))))) } pub fn view_track_devices <'a> (&'a self, theme: ItemTheme) -> impl Content + 'a { let mut h = 2u16; for track in self.tracks().iter() { - h = h.max(track.devices.len() as u16); + h = h.max(track.devices.len() as u16 * 2); } self.view_track_row_section( theme, - button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false), + button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false), button_2("D", "+", false), 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 + 1, - Tui::bg(track.color.dark.rgb, Align::nw(Map::south(1, move||0..h, - |_, index|format!("·d{index:02} {}", "--------")))))); + Tui::bg(track.color.dark.rgb, Align::nw(Map::south(2, move||0..h, + |_, index|Fixed::xy(track.width as u16, 2, Tui::bg(ItemTheme::G[32].base.rgb, + Align::nw(format!(" · {}", "--"))))))))); } })) } @@ -129,7 +142,7 @@ pub trait TracksView: theme: ItemTheme, button: impl Content, button_add: impl Content, - content: impl Content + content: impl Content ) -> impl Content { Bsp::w(Fill::y(Fixed::x(4, Align::nw(button_add))), Bsp::e(Fixed::x(20, Fill::y(Align::nw(button))), Fill::xy(Align::c(content)))) @@ -201,7 +214,7 @@ pub trait TracksView: } self.view_track_row_section( theme, - button_2("i", "nput", false), + button_2("i", "nput", false), button_2("I", "+", false), Tui::bg(theme.darker.rgb, Align::w(Fill::x( Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ @@ -230,7 +243,7 @@ pub trait ScenesView: HasSceneScroll + HasClipsSize + Send + - Sync + Sync { /// Default scene height. const H_SCENE: usize = 2; From baad8254a229491a796bcdc1f0731025a0d2f2ea Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 18 May 2025 00:23:00 +0300 Subject: [PATCH 5/5] add buttons --- crates/device/src/arranger/arranger_view.rs | 30 ++++++++-------- crates/device/src/lib.rs | 39 +++++++++++++++++++++ deps/tengri | 2 +- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index 5f45499b..c9ebc98a 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -13,26 +13,26 @@ impl Arrangement { Bsp::w(Fixed::x(4, button_2("I", "+", false)), Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ for (index, track, x1, x2) in self.tracks_with_sizes() { - add(&Align::w(row!( + add(&Tui::bg(track.color.dark.rgb, Align::w(Fixed::x(track.width as u16, 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 "), - ))) + ))))) } }))))); for (index, port) in self.midi_ins().iter().enumerate() { - add(&Fixed::y(1, - Bsp::e(Fixed::x(20, Align::w(format!(" ● i{index:02} {}", port.name()))), - Bsp::w(Fixed::x(4, ()), - Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ - for (index, track, x1, x2) in self.tracks_with_sizes() { - add(&Align::w(row!( - Either(track.sequencer.monitoring, Tui::fg(Green, " ● "), " · "), - Either(track.sequencer.recording, Tui::fg(Red, " ● "), " · "), - Either(track.sequencer.overdub, Tui::fg(Yellow, " ● "), " · "), - ))) - } - }))))); + add(&Fixed::y(1, Bsp::e( + Fixed::x(20, Align::w(Bsp::e(" ● ", Tui::bold(true, Tui::fg(Rgb(255,255,255),port.name()))))), + Bsp::w(Fixed::x(4, ()), + Stack::east(move|add: &mut dyn FnMut(&dyn Render)|{ + for (index, track, x1, x2) in self.tracks_with_sizes() { + add(&Tui::bg(track.color.darker.rgb, Align::w(Fixed::x(track.width as u16, row!( + Either(track.sequencer.monitoring, Tui::fg(Green, " ● "), " · "), + Either(track.sequencer.recording, Tui::fg(Red, " ● "), " · "), + Either(track.sequencer.overdub, Tui::fg(Yellow, " ● "), " · "), + ))))) + } + }))))); } }) } @@ -47,7 +47,7 @@ impl Arrangement { Fixed::y(h - 1, Fill::xy(Align::nw(Stack::south(|add: &mut dyn FnMut(&dyn Render)|{ for (index, port) in self.midi_outs().iter().enumerate() { add(&Fixed::y(1,Fill::x(Bsp::e( - Align::w(Bsp::e(format!(" ● o{index:02} "), Tui::fg(Rgb(255,255,255),Tui::bold(true, port.name())))), + Align::w(Bsp::e(" ● ", Tui::fg(Rgb(255,255,255),Tui::bold(true, port.name())))), Fill::x(Align::e(format!("{}/{} ", port.port().get_connections().len(), port.conn().len()))))))); diff --git a/crates/device/src/lib.rs b/crates/device/src/lib.rs index 6041e16c..a4ca5930 100644 --- a/crates/device/src/lib.rs +++ b/crates/device/src/lib.rs @@ -38,3 +38,42 @@ mod dialog; pub use self::dialog::*; #[cfg(feature = "vst2")] mod vst2; #[cfg(feature = "vst2")] pub use self::vst2::*; #[cfg(feature = "vst3")] mod vst3; #[cfg(feature = "vst3")] pub use self::vst3::*; #[cfg(feature = "clap")] mod clap; #[cfg(feature = "clap")] pub use self::clap::*; + +pub fn button_2 <'a> ( + key: impl Content + 'a, label: impl Content + 'a, editing: bool, +) -> impl Content + 'a { + let key = Tui::fg_bg(Tui::orange(), Tui::g(0), Bsp::e( + Tui::fg(Tui::g(0), "▐"), + Bsp::e(key, Tui::fg(Tui::g(96), "▐")) + )); + let label = When::new(!editing, Tui::fg_bg(Tui::g(255), Tui::g(96), label)); + Tui::bold(true, Bsp::e(key, label)) +} + +pub fn button_3 <'a, K, L, V> ( + key: K, + label: L, + value: V, + editing: bool, +) -> impl Content + 'a where + K: Content + 'a, + L: Content + 'a, + V: Content + 'a, +{ + let key = Tui::fg_bg(Tui::orange(), Tui::g(0), + Bsp::e(Tui::fg(Tui::g(0), "▐"), Bsp::e(key, Tui::fg(if editing { + Tui::g(128) + } else { + Tui::g(96) + }, "▐")))); + let label = Bsp::e( + When::new(!editing, Bsp::e( + Tui::fg_bg(Tui::g(255), Tui::g(96), label), + Tui::fg_bg(Tui::g(128), Tui::g(96), "▐"), + )), + Bsp::e( + Tui::fg_bg(Tui::g(224), Tui::g(128), value), + Tui::fg_bg(Tui::g(128), Reset, "▌"), + )); + Tui::bold(true, Bsp::e(key, label)) +} diff --git a/deps/tengri b/deps/tengri index 9a12e0c7..921378b6 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit 9a12e0c7bab24cb708d503e860d93677ae306961 +Subproject commit 921378b6dbb38d4f301f688abd1cfef9bdc0f941