reorder unified transport widgets

This commit is contained in:
🪞👃🪞 2024-09-12 15:39:59 +03:00
parent 77519dbb5c
commit 630974d394

View file

@ -1,5 +1,7 @@
use crate::*; use crate::*;
const CORNERS: Corners = Corners(NOT_DIM_GREEN);
/// Stores and displays time-related state. /// Stores and displays time-related state.
pub struct TransportToolbar<E: Engine> { pub struct TransportToolbar<E: Engine> {
/// Enable metronome? /// Enable metronome?
@ -187,6 +189,36 @@ impl<E: Engine> Audio for TransportToolbar<E> {
Control::Continue Control::Continue
} }
} }
impl Handle<Tui> for TransportToolbar<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
match from.event() {
key!(KeyCode::Left) => {
self.focus_prev();
Ok(Some(true))
},
key!(KeyCode::Right) => {
self.focus_next();
Ok(Some(true))
},
_ => self.focused_mut().handle(from)
}
}
}
impl Content for TransportToolbar<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Split::right(|add|{
add(&self.playing)?;
add(&self.bpm)?;
add(&self.quant)?;
add(&self.sync)?;
add(&self.clock)?;
Ok(())
})
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
pub struct TransportPlayPauseButton<E: Engine> { pub struct TransportPlayPauseButton<E: Engine> {
pub _engine: PhantomData<E>, pub _engine: PhantomData<E>,
@ -202,6 +234,8 @@ impl Focusable<Tui> for TransportPlayPauseButton<Tui> {
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
pub struct TransportBPM<E: Engine> { pub struct TransportBPM<E: Engine> {
pub _engine: PhantomData<E>, pub _engine: PhantomData<E>,
pub value: f64, pub value: f64,
@ -215,156 +249,21 @@ impl Focusable<Tui> for TransportBPM<Tui> {
self.focused = focused self.focused = focused
} }
} }
pub struct TransportQuantize<E: Engine> {
pub _engine: PhantomData<E>,
pub value: usize,
pub focused: bool
}
impl Focusable<Tui> for TransportQuantize<Tui> {
fn is_focused (&self) -> bool {
self.focused
}
fn set_focused (&mut self, focused: bool) {
self.focused = focused
}
}
pub struct TransportSync<E: Engine> {
pub _engine: PhantomData<E>,
pub value: usize,
pub focused: bool
}
impl Focusable<Tui> for TransportSync<Tui> {
fn is_focused (&self) -> bool {
self.focused
}
fn set_focused (&mut self, focused: bool) {
self.focused = focused
}
}
pub struct TransportClock<E: Engine> {
pub _engine: PhantomData<E>,
pub frame: usize,
pub pulse: usize,
pub ppq: usize,
pub usecs: usize,
pub focused: bool,
}
impl Focusable<Tui> for TransportClock<Tui> {
fn is_focused (&self) -> bool {
self.focused
}
fn set_focused (&mut self, focused: bool) {
self.focused = focused
}
}
impl Handle<Tui> for TransportToolbar<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
Ok(None)
//Ok(
//from.key(KeyCode::Right).does(||self.focus_next())?
//||
//from.key(KeyCode::Left).does(||self.focus_prev())?
//||
//from.key(KeyCode::Char(' ')).does(||self.toggle_play())?
//)
}
}
impl Handle<Tui> for TransportPlayPauseButton<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
Ok(None)
}
}
impl Handle<Tui> for TransportBPM<Tui> { impl Handle<Tui> for TransportBPM<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> { fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
//TransportFocus::BPM => { match from.event() {
//transport.timebase.bpm.fetch_add(1.0, Ordering::Relaxed); key!(KeyCode::Char(',')) => {
//}, self.bpm().fetch_sub(1.0, Ordering::Relaxed);
//TransportFocus::BPM => { Ok(Some(true))
//transport.timebase.bpm.fetch_sub(1.0, Ordering::Relaxed); },
//}, key!(KeyCode::Char('.')) => {
Ok(None) self.bpm().fetch_add(1.0, Ordering::Relaxed);
Ok(Some(true))
},
_ => Ok(None)
}
} }
} }
impl Handle<Tui> for TransportQuantize<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
//TransportFocus::Quant => {
//transport.quant.value = next_note_length(transport.quant)
//},
//TransportFocus::Quant => {
//transport.quant.value = prev_note_length(transport.quant);
//},
Ok(None)
}
}
impl Handle<Tui> for TransportSync<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
//TransportFocus::Sync => {
//transport.sync.value = next_note_length(transport.sync)
//},
//TransportFocus::Sync => {
//transport.sync.value = prev_note_length(transport.sync);
//},
Ok(None)
}
}
impl Handle<Tui> for TransportClock<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
//TransportFocus::Sync => {
//transport.sync.value = next_note_length(transport.sync)
//},
//TransportFocus::Sync => {
//transport.sync.value = prev_note_length(transport.sync);
//},
Ok(None)
}
}
const CORNERS: Corners = Corners(NOT_DIM_GREEN);
impl Content for TransportToolbar<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Split::right(|add|{
add(&self.playing)?;
add(&self.bpm)?;
add(&self.quant)?;
add(&self.sync)?;
add(&self.clock)?;
Ok(())
})
}
}
impl Content for TransportPlayPauseButton<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Layers::new(|add|{
//add(&self.focused.then_some(CORNERS))?;
add(&Styled(match self.value {
Some(TransportState::Stopped) => Some(GRAY_DIM.bold()),
Some(TransportState::Starting) => Some(GRAY_NOT_DIM_BOLD),
Some(TransportState::Rolling) => Some(WHITE_NOT_DIM_BOLD),
_ => unreachable!(),
}, match self.value {
Some(TransportState::Rolling) => "▶ PLAYING",
Some(TransportState::Starting) => "READY ...",
Some(TransportState::Stopped) => "⏹ STOPPED",
_ => unreachable!(),
}))?;
Ok(())
})
}
}
impl Widget for TransportBPM<Tui> { impl Widget for TransportBPM<Tui> {
type Engine = Tui; type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
@ -389,6 +288,36 @@ impl Widget for TransportBPM<Tui> {
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
pub struct TransportQuantize<E: Engine> {
pub _engine: PhantomData<E>,
pub value: usize,
pub focused: bool
}
impl Focusable<Tui> for TransportQuantize<Tui> {
fn is_focused (&self) -> bool {
self.focused
}
fn set_focused (&mut self, focused: bool) {
self.focused = focused
}
}
impl Handle<Tui> for TransportQuantize<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
match from.event() {
key!(KeyCode::Char(',')) => {
transport.quant.value = prev_note_length(transport.quant);
Ok(Some(true))
},
key!(KeyCode::Char('.')) => {
transport.quant.value = next_note_length(transport.quant);
Ok(Some(true))
},
_ => Ok(None)
}
}
}
impl Widget for TransportQuantize<Tui> { impl Widget for TransportQuantize<Tui> {
type Engine = Tui; type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
@ -412,6 +341,36 @@ impl Widget for TransportQuantize<Tui> {
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
pub struct TransportSync<E: Engine> {
pub _engine: PhantomData<E>,
pub value: usize,
pub focused: bool
}
impl Focusable<Tui> for TransportSync<Tui> {
fn is_focused (&self) -> bool {
self.focused
}
fn set_focused (&mut self, focused: bool) {
self.focused = focused
}
}
impl Handle<Tui> for TransportSync<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
match from.event() {
key!(KeyCode::Char(',')) => {
transport.sync.value = prev_note_length(transport.quant);
Ok(Some(true))
},
key!(KeyCode::Char('.')) => {
transport.sync.value = next_note_length(transport.quant);
Ok(Some(true))
},
_ => Ok(None)
}
}
}
impl Widget for TransportSync<Tui> { impl Widget for TransportSync<Tui> {
type Engine = Tui; type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
@ -435,6 +394,29 @@ impl Widget for TransportSync<Tui> {
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
pub struct TransportClock<E: Engine> {
pub _engine: PhantomData<E>,
pub frame: usize,
pub pulse: usize,
pub ppq: usize,
pub usecs: usize,
pub focused: bool,
}
impl Focusable<Tui> for TransportClock<Tui> {
fn is_focused (&self) -> bool {
self.focused
}
fn set_focused (&mut self, focused: bool) {
self.focused = focused
}
}
impl Handle<Tui> for TransportClock<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
Ok(None)
}
}
impl Widget for TransportClock<Tui> { impl Widget for TransportClock<Tui> {
type Engine = Tui; type Engine = Tui;
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
@ -462,3 +444,34 @@ impl Widget for TransportClock<Tui> {
Ok(Some(area)) Ok(Some(area))
} }
} }
impl Handle<Tui> for TransportPlayPauseButton<Tui> {
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
match from.event() {
key!(KeyCode::Enter) => {
self.toggle();
Ok(Some(true))
}
_ => Ok(None)
}
}
}
impl Content for TransportPlayPauseButton<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Layers::new(|add|{
//add(&self.focused.then_some(CORNERS))?;
add(&Styled(match self.value {
Some(TransportState::Stopped) => Some(GRAY_DIM.bold()),
Some(TransportState::Starting) => Some(GRAY_NOT_DIM_BOLD),
Some(TransportState::Rolling) => Some(WHITE_NOT_DIM_BOLD),
_ => unreachable!(),
}, match self.value {
Some(TransportState::Rolling) => "▶ PLAYING",
Some(TransportState::Starting) => "READY ...",
Some(TransportState::Stopped) => "⏹ STOPPED",
_ => unreachable!(),
}))?;
Ok(())
})
}
}