diff --git a/crates/tek_tui/src/tui_content.rs b/crates/tek_tui/src/tui_content.rs index 2cccd6a2..2ba9ca50 100644 --- a/crates/tek_tui/src/tui_content.rs +++ b/crates/tek_tui/src/tui_content.rs @@ -4,9 +4,9 @@ impl<'a, T: TransportViewState> Content for TransportView<'a, T> { type Engine = Tui; fn content (&self) -> impl Widget { let state = self.0; - let focused = state.transport_focused(); + let selected = state.transport_selected(); lay!( - state.transport_selected().wrap(focused, TransportFocus::PlayPause, &Styled( + selected.wrap(TransportFocus::PlayPause, &Styled( None, match *state.transport_state().read().unwrap() { Some(TransportState::Rolling) => "▶ PLAYING", @@ -17,19 +17,19 @@ impl<'a, T: TransportViewState> Content for TransportView<'a, T> { ).min_xy(11, 2).push_x(1)).align_x().fill_x(), row!( - state.transport_selected().wrap(focused, TransportFocus::Bpm, &Outset::X(1u16, { + selected.wrap(TransportFocus::Bpm, &Outset::X(1u16, { let bpm = state.transport_bpm_value(); row! { "BPM ", format!("{}.{:03}", bpm as usize, (bpm * 1000.0) % 1000.0) } })), //let quant = state.focus().wrap(state.focused(), TransportFocus::Quant, &Outset::X(1u16, row! { //"QUANT ", ppq_to_name(state.0.quant as usize) //})), - state.transport_selected().wrap(focused, TransportFocus::Sync, &Outset::X(1u16, row! { + selected.wrap(TransportFocus::Sync, &Outset::X(1u16, row! { "SYNC ", pulses_to_name(state.transport_sync_value() as usize) })) ).align_w().fill_x(), - state.transport_selected().wrap(focused, TransportFocus::Clock, &{ + selected.wrap(TransportFocus::Clock, &{ let time1 = state.transport_format_beat(); let time2 = state.transport_format_msu(); row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1) diff --git a/crates/tek_tui/src/tui_focus.rs b/crates/tek_tui/src/tui_focus.rs index eb5363b2..d8d9ebdf 100644 --- a/crates/tek_tui/src/tui_focus.rs +++ b/crates/tek_tui/src/tui_focus.rs @@ -40,6 +40,33 @@ pub enum ArrangerFocus { PhraseEditor, } +pub trait FocusWrap { + fn wrap <'a, W: Widget> (self, focus: T, content: &'a W) + -> impl Widget + 'a; +} + +impl FocusWrap for TransportFocus { + fn wrap <'a, W: Widget> (self, focus: TransportFocus, content: &'a W) + -> impl Widget + 'a + { + let focused = focus == self; + let corners = focused.then_some(CORNERS); + let highlight = focused.then_some(Background(Color::Rgb(60, 70, 50))); + lay!(corners, highlight, *content) + } +} + +impl FocusWrap for Option { + fn wrap <'a, W: Widget> (self, focus: TransportFocus, content: &'a W) + -> impl Widget + 'a + { + let focused = Some(focus) == self; + let corners = focused.then_some(CORNERS); + let highlight = focused.then_some(Background(Color::Rgb(60, 70, 50))); + lay!(corners, highlight, *content) + } +} + impl TransportFocus { pub fn next (&mut self) { *self = match self { @@ -59,14 +86,6 @@ impl TransportFocus { Self::Clock => Self::Sync, } } - pub fn wrap <'a, W: Widget> ( - self, parent_focus: bool, focus: Self, widget: &'a W - ) -> impl Widget + 'a { - let focused = parent_focus && focus == self; - let corners = focused.then_some(CORNERS); - let highlight = focused.then_some(Background(Color::Rgb(60, 70, 50))); - lay!(corners, highlight, *widget) - } } macro_rules! impl_focus { diff --git a/crates/tek_tui/src/tui_view.rs b/crates/tek_tui/src/tui_view.rs index dcd0ee05..98e7b34f 100644 --- a/crates/tek_tui/src/tui_view.rs +++ b/crates/tek_tui/src/tui_view.rs @@ -7,8 +7,10 @@ pub struct PhrasesView<'a, T: PhrasesViewState>(pub &'a T); pub struct PhraseView<'a, T: PhraseViewState>(pub &'a T); pub trait TransportViewState: ClockApi + Send + Sync { - fn transport_selected (&self) -> TransportFocus; - fn transport_focused (&self) -> bool; + fn transport_selected (&self) -> Option; + fn transport_focused (&self) -> bool { + self.transport_selected().is_some() + } fn transport_bpm_value (&self) -> f64 { self.bpm().get() } @@ -22,21 +24,33 @@ pub trait TransportViewState: ClockApi + Send + Sync { self.current().usec.format_msu() } } -macro_rules! impl_transport_view_state { - ($Struct:ident :: $field:ident) => { - impl TransportViewState for $Struct { - fn transport_selected (&self) -> TransportFocus { - self.focused().inner() - } - fn transport_focused (&self) -> bool { - true - } +impl TransportViewState for TransportTui { + fn transport_selected (&self) -> Option { + if let AppFocus::Content(focus) = self.focus.inner() { + Some(focus) + } else { + None + } + } +} +impl TransportViewState for SequencerTui { + fn transport_selected (&self) -> Option { + if let AppFocus::Content(SequencerFocus::Transport(focus)) = self.focus.inner() { + Some(focus) + } else { + None + } + } +} +impl TransportViewState for ArrangerTui { + fn transport_selected (&self) -> Option { + if let AppFocus::Content(ArrangerFocus::Transport(focus)) = self.focus.inner() { + Some(focus) + } else { + None } } } -impl_transport_view_state!(TransportTui::clock); -impl_transport_view_state!(SequencerTui::clock); -impl_transport_view_state!(ArrangerTui::clock); pub trait ArrangerViewState { fn arranger_focused (&self) -> bool;