wip: focus refactor, e10

This commit is contained in:
🪞👃🪞 2024-11-23 15:12:21 +01:00
parent 6127aa4b30
commit 6a25a3b858
3 changed files with 60 additions and 27 deletions

View file

@ -4,9 +4,9 @@ impl<'a, T: TransportViewState> Content for TransportView<'a, T> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
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)

View file

@ -40,6 +40,33 @@ pub enum ArrangerFocus {
PhraseEditor,
}
pub trait FocusWrap<T> {
fn wrap <'a, W: Widget<Engine = Tui>> (self, focus: T, content: &'a W)
-> impl Widget<Engine = Tui> + 'a;
}
impl FocusWrap<TransportFocus> for TransportFocus {
fn wrap <'a, W: Widget<Engine = Tui>> (self, focus: TransportFocus, content: &'a W)
-> impl Widget<Engine = Tui> + '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<TransportFocus> for Option<TransportFocus> {
fn wrap <'a, W: Widget<Engine = Tui>> (self, focus: TransportFocus, content: &'a W)
-> impl Widget<Engine = Tui> + '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<Engine = Tui>> (
self, parent_focus: bool, focus: Self, widget: &'a W
) -> impl Widget<Engine = Tui> + '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 {

View file

@ -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<TransportFocus>;
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<TransportFocus> {
if let AppFocus::Content(focus) = self.focus.inner() {
Some(focus)
} else {
None
}
}
}
impl TransportViewState for SequencerTui {
fn transport_selected (&self) -> Option<TransportFocus> {
if let AppFocus::Content(SequencerFocus::Transport(focus)) = self.focus.inner() {
Some(focus)
} else {
None
}
}
}
impl TransportViewState for ArrangerTui {
fn transport_selected (&self) -> Option<TransportFocus> {
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;