From 4be2df134748e6ee0cb8fde0fadcbb84f1c4e6db Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 3 Oct 2024 15:52:21 +0300 Subject: [PATCH] add focus proxy for sequencers --- crates/tek_sequencer/src/main_arranger.rs | 80 ++++++++++++++++++----- crates/tek_sequencer/src/sequencer_tui.rs | 8 +++ 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/crates/tek_sequencer/src/main_arranger.rs b/crates/tek_sequencer/src/main_arranger.rs index 39faaa82..af95d08b 100644 --- a/crates/tek_sequencer/src/main_arranger.rs +++ b/crates/tek_sequencer/src/main_arranger.rs @@ -48,7 +48,8 @@ impl ArrangerCli { transport, show_sequencer: Some(tek_core::Direction::Down), arranger, - focus: 0 + focus: 0, + sequencer_proxy: SequencerProxy(Default::default(), false) })))?; Ok(()) } @@ -56,13 +57,31 @@ impl ArrangerCli { /// Root level object for standalone `tek_arranger` struct ArrangerStandalone { /// Controls the JACK transport. - transport: Option>, + transport: Option>, /// Contains all the sequencers. - arranger: Arranger, + arranger: Arranger, /// This allows the sequencer view to be moved or hidden. - show_sequencer: Option, - /// - focus: usize, + show_sequencer: Option, + /// Index of currently focused component + focus: usize, + /// Focus target that passes events down to sequencer + sequencer_proxy: SequencerProxy, +} +impl ArrangerStandalone { + fn sequencer (&self) -> Option<&Sequencer> { + if self.show_sequencer.is_some() { + self.arranger.sequencer() + } else { + None + } + } + fn sequencer_mut (&mut self) -> Option<&mut Sequencer> { + if self.show_sequencer.is_some() { + self.arranger.sequencer_mut() + } else { + None + } + } } /// The standalone arranger consists of transport, clip grid, and sequencer. impl Content for ArrangerStandalone { @@ -94,6 +113,16 @@ impl Content for ArrangerStandalone { /// Handle top-level events in standalone arranger. impl Handle for ArrangerStandalone { fn handle (&mut self, from: &TuiInput) -> Perhaps { + let focus = self.focus; + let is_first_row = self.arranger.is_first_row(); + let is_last_row = self.arranger.is_last_row(); + let mut focused_handle = || { + if focus == 2 { + self.arranger.sequencer_mut().handle(from) + } else { + self.focused_mut().handle(from) + } + }; match from.event() { key!(KeyCode::Char(' ')) => { if let Some(ref mut transport) = self.transport { @@ -109,38 +138,55 @@ impl Handle for ArrangerStandalone { self.focus_prev(); }, key!(KeyCode::Down) => { - if self.focus == 0 { + if focus == 0 { self.focus_next(); - } else if self.focus == 1 && self.arranger.is_last_row() { + } else if focus == 1 && is_last_row { self.focus_next(); } else { - return self.focused_mut().handle(from) + return focused_handle() } }, key!(KeyCode::Up) => { - if self.focus == 1 && self.arranger.is_first_row() { + if focus == 1 && is_first_row { self.focus_prev(); } else { - return self.focused_mut().handle(from) + return focused_handle() } }, - _ => return self.focused_mut().handle(from) + _ => return focused_handle() } Ok(Some(true)) } } /// Focusable items in standalone arranger. -impl Focus<2, Tui> for ArrangerStandalone { +impl Focus<3, Tui> for ArrangerStandalone { fn focus (&self) -> usize { self.focus } fn focus_mut (&mut self) -> &mut usize { &mut self.focus } - fn focusable (&self) -> [&dyn Focusable;2] { - focusables!(self.transport, self.arranger) + fn focusable (&self) -> [&dyn Focusable;3] { + focusables!(self.transport, self.arranger, self.sequencer_proxy) } - fn focusable_mut (&mut self) -> [&mut dyn Focusable;2] { - focusables_mut!(self.transport, self.arranger) + fn focusable_mut (&mut self) -> [&mut dyn Focusable;3] { + focusables_mut!(self.transport, self.arranger, self.sequencer_proxy) + } +} +#[derive(Default)] +struct SequencerProxy(PhantomData, bool); +impl Handle for SequencerProxy { + fn handle (&mut self, _: &TuiInput) -> Perhaps { unreachable!() } +} +impl Content for SequencerProxy { + type Engine = Tui; + fn content (&self) -> impl Widget { "" } +} +impl Focusable for SequencerProxy { + fn is_focused (&self) -> bool { + self.1 + } + fn set_focused (&mut self, focus: bool) { + self.1 = focus } } diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index 37db6d56..c2e51f8b 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -885,6 +885,14 @@ impl Content for Sequencer { .fg(Color::Rgb(70, 80, 50)))) } } +impl Focusable for Sequencer { + fn is_focused (&self) -> bool { + self.focused + } + fn set_focused (&mut self, focused: bool) { + self.focused = focused + } +} /// Colors of piano keys const KEY_COLORS: [(Color, Color);6] = [