use crate::*; impl TransportToolbar { fn handle_play_pause (&mut self, from: &TuiInput) -> Perhaps { match from.event() { key!(KeyCode::Enter) => self.toggle_play().map(|_|())?, _ => return Ok(None) } Ok(Some(true)) } fn handle_bpm (&mut self, from: &TuiInput) -> Perhaps { match from.event() { key!(KeyCode::Char(',')) => { self.bpm -= 1.0; }, key!(KeyCode::Char('.')) => { self.bpm += 1.0; }, key!(KeyCode::Char('<')) => { self.bpm -= 0.001; }, key!(KeyCode::Char('>')) => { self.bpm += 0.001; }, _ => return Ok(None) } Ok(Some(true)) } fn handle_quant (&mut self, from: &TuiInput) -> Perhaps { match from.event() { key!(KeyCode::Char(',')) => { self.quant = prev_note_length(self.quant); }, key!(KeyCode::Char('.')) => { self.quant = next_note_length(self.quant); }, _ => return Ok(None) } return Ok(Some(true)) } fn handle_sync (&mut self, from: &TuiInput) -> Perhaps { match from.event() { key!(KeyCode::Char(',')) => { self.sync = prev_note_length(self.sync); }, key!(KeyCode::Char('.')) => { self.sync = next_note_length(self.sync); }, _ => return Ok(None) } return Ok(Some(true)) } } impl Handle for TransportToolbar { fn handle (&mut self, from: &TuiInput) -> Perhaps { match from.event() { key!(KeyCode::Left) => { self.focus.prev(); }, key!(KeyCode::Right) => { self.focus.next(); }, _ => match self.focus { TransportToolbarFocus::PlayPause => return self.handle_play_pause(from), TransportToolbarFocus::Bpm => return self.handle_bpm(from), TransportToolbarFocus::Quant => return self.handle_quant(from), TransportToolbarFocus::Sync => return self.handle_sync(from), TransportToolbarFocus::Clock => {/*todo*/}, } } Ok(Some(true)) } } impl Content for TransportToolbar { type Engine = Tui; fn content (&self) -> impl Widget { row!( self.focus.wrap(self.focused, TransportToolbarFocus::PlayPause, &Styled( match self.playing { 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.playing { Some(TransportState::Rolling) => "▶ PLAYING", Some(TransportState::Starting) => "READY ...", Some(TransportState::Stopped) => "⏹ STOPPED", _ => unreachable!(), } ).min_xy(11, 2).push_x(1)), self.focus.wrap(self.focused, TransportToolbarFocus::Bpm, &Outset::X(1u16, col! { "BPM", format!("{}.{:03}", self.bpm as usize, (self.bpm * 1000.0) % 1000.0) })), self.focus.wrap(self.focused, TransportToolbarFocus::Quant, &Outset::X(1u16, col! { "QUANT", ppq_to_name(self.quant as usize) })), self.focus.wrap(self.focused, TransportToolbarFocus::Sync, &Outset::X(1u16, col! { "SYNC", ppq_to_name(self.sync as usize) })), self.focus.wrap(self.focused, TransportToolbarFocus::Clock, &{ let Self { frame: _frame, pulse, ppq, usecs, .. } = self; let (beats, pulses) = if *ppq > 0 { (pulse / ppq, pulse % ppq) } else { (0, 0) }; let (bars, beats) = ((beats / 4) + 1, (beats % 4) + 1); let (seconds, msecs) = (usecs / 1000000, usecs / 1000 % 1000); let (minutes, seconds) = (seconds / 60, seconds % 60); let time1 = format!("{bars}.{beats}.{pulses:02}"); let time2 = format!("{minutes}:{seconds:02}:{msecs:03}"); col!(time1.as_str(), time2.as_str()).outset_x(1) }), ).fill_x().bg(Color::Rgb(40, 50, 30)) } } impl TransportToolbarFocus { 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) } }