use crate::*; #[derive(Clone, PartialEq)] pub enum SequencerAppCommand { Focus(FocusCommand), Transport(TransportCommand), Phrases(PhrasePoolCommand), Editor(PhraseEditorCommand), } impl Handle for SequencerApp { fn handle (&mut self, i: &TuiInput) -> Perhaps { if let Some(entered) = self.entered() { use SequencerFocus::*; if let Some(true) = match entered { Transport => self.transport.as_mut().map(|t|t.handle(i)).transpose()?.flatten(), PhrasePool => self.phrases.write().unwrap().handle(i)?, PhraseEditor => self.editor.handle(i)?, } { return Ok(Some(true)) } } if let Some(command) = SequencerCommand::input_to_command(self, i) { let _undo = command.execute(self)?; return Ok(Some(true)) } Ok(None) } } impl Command> for SequencerAppCommand { fn execute (self, state: &mut SequencerApp) -> Perhaps { match self { Self::Focus(cmd) => { return delegate(cmd, Self::Focus, state) }, Self::Phrases(cmd) => { return delegate(cmd, Self::Phrases, &mut*state.phrases.write().unwrap()) }, Self::Editor(cmd) => { return delegate(cmd, Self::Editor, &mut state.editor) }, Self::Transport(cmd) => if let Some(ref transport) = state.transport { return delegate(cmd, Self::Transport, &mut*transport.write().unwrap()) }, } Ok(None) } } impl InputToCommand> for SequencerCommand { fn input_to_command (state: &SequencerApp, input: &TuiInput) -> Option { use SequencerCommand::*; use FocusCommand::*; match input.event() { key!(KeyCode::Tab) => Some(Focus(Next)), key!(Shift-KeyCode::Tab) => Some(Focus(Prev)), key!(KeyCode::BackTab) => Some(Focus(Prev)), key!(Shift-KeyCode::BackTab) => Some(Focus(Prev)), key!(KeyCode::Up) => Some(Focus(Up)), key!(KeyCode::Down) => Some(Focus(Down)), key!(KeyCode::Left) => Some(Focus(Left)), key!(KeyCode::Right) => Some(Focus(Right)), key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)), _ => match state.focused() { SequencerFocus::Transport => if let Some(t) = state.transport.as_ref() { TransportCommand::input_to_command(&*t.read().unwrap(), input).map(Transport) } else { None }, SequencerFocus::PhrasePool => PhrasePoolCommand::input_to_command(&*state.phrases.read().unwrap(), input) .map(Phrases), SequencerFocus::PhraseEditor => PhraseEditorCommand::input_to_command(&state.editor, input) .map(Editor), } } } }