diff --git a/src/device/sequencer.rs b/src/device/sequencer.rs index 63b3f64c..d4511587 100644 --- a/src/device/sequencer.rs +++ b/src/device/sequencer.rs @@ -415,10 +415,10 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually Usually { - handle_keymap(COMMANDS, s, event) + handle_keymap(s, event, KEYMAP) } -pub const COMMANDS: &'static [KeyBinding] = keymap!(Sequencer { +pub const KEYMAP: &'static [KeyBinding] = keymap!(Sequencer { [Up, NONE, "cursor_up", "move cursor up", cursor_up], [Down, NONE, "cursor_down", "move cursor down", cursor_down], [Left, NONE, "cursor_left", "move cursor left", cursor_left], @@ -444,9 +444,10 @@ pub const COMMANDS: &'static [KeyBinding] = keymap!(Sequencer { [Char('s'), SHIFT, "sync", "Focus sync selector", nop] }); -fn nop (_: &mut Sequencer) { +fn nop (_: &mut Sequencer) -> Usually { + Ok(false) } -fn note_add (s: &mut Sequencer) { +fn note_add (s: &mut Sequencer) -> Usually { let pos = s.transport.query().unwrap().pos; let usecs = s.timebase.frame_to_usec(pos.frame() as usize); let step = (s.time_axis.0 + s.time_cursor) as u32; @@ -464,62 +465,75 @@ fn note_add (s: &mut Sequencer) { s.sequence.get_mut(&end).unwrap().push(note_off.clone()); } else { s.sequence.insert(end, vec![note_off]); - } + }; + Ok(true) } -fn note_del (_: &mut Sequencer) { +fn note_del (_: &mut Sequencer) -> Usually { + Ok(true) } -fn time_cursor_inc (s: &mut Sequencer) { +fn time_cursor_inc (s: &mut Sequencer) -> Usually { let time = s.time_axis.1 - s.time_axis.0; - s.time_cursor = ((time + s.time_cursor) + 1) % time + s.time_cursor = ((time + s.time_cursor) + 1) % time; + Ok(true) } -fn time_cursor_dec (s: &mut Sequencer) { +fn time_cursor_dec (s: &mut Sequencer) -> Usually { let time = s.time_axis.1 - s.time_axis.0; - s.time_cursor = ((time + s.time_cursor) - 1) % time + s.time_cursor = ((time + s.time_cursor) - 1) % time; + Ok(true) } -fn note_cursor_inc (s: &mut Sequencer) { +fn note_cursor_inc (s: &mut Sequencer) -> Usually { let note = s.note_axis.1 - s.note_axis.0; - s.note_cursor = ((note + s.note_cursor) + 1) % note + s.note_cursor = ((note + s.note_cursor) + 1) % note; + Ok(true) } -fn note_cursor_dec (s: &mut Sequencer) { +fn note_cursor_dec (s: &mut Sequencer) -> Usually { let note = s.note_axis.1 - s.note_axis.0; - s.note_cursor = ((note + s.note_cursor) - 1) % note + s.note_cursor = ((note + s.note_cursor) - 1) % note; + Ok(true) } -fn cursor_up (s: &mut Sequencer) { +fn cursor_up (s: &mut Sequencer) -> Usually { match s.mode { SequencerView::Vertical => time_cursor_dec(s), SequencerView::Horizontal => note_cursor_dec(s), _ => unimplemented!() - } + }; + Ok(true) } -fn cursor_down (s: &mut Sequencer) { +fn cursor_down (s: &mut Sequencer) -> Usually { match s.mode { SequencerView::Vertical => time_cursor_inc(s), SequencerView::Horizontal => note_cursor_inc(s), _ => unimplemented!() - } + }; + Ok(true) } -fn cursor_left (s: &mut Sequencer) { +fn cursor_left (s: &mut Sequencer) -> Usually { match s.mode { SequencerView::Vertical => note_cursor_dec(s), SequencerView::Horizontal => time_cursor_dec(s), _ => unimplemented!() - } + }; + Ok(true) } -fn cursor_right (s: &mut Sequencer) { +fn cursor_right (s: &mut Sequencer) -> Usually { match s.mode { SequencerView::Vertical => note_cursor_inc(s), SequencerView::Horizontal => time_cursor_inc(s), _ => unimplemented!() - } + }; + Ok(true) } -fn cursor_duration_inc (_: &mut Sequencer) { +fn cursor_duration_inc (_: &mut Sequencer) -> Usually { //s.cursor.2 = s.cursor.2 + 1 + Ok(true) } -fn cursor_duration_dec (_: &mut Sequencer) { +fn cursor_duration_dec (_: &mut Sequencer) -> Usually { //if s.cursor.2 > 0 { s.cursor.2 = s.cursor.2 - 1 } + Ok(true) } -fn mode_next (s: &mut Sequencer) { - s.mode = s.mode.next() +fn mode_next (s: &mut Sequencer) -> Usually { + s.mode = s.mode.next(); + Ok(true) } impl SequencerView { fn next (&self) -> Self { @@ -530,27 +544,33 @@ impl SequencerView { } } } -fn stop_and_rewind (s: &mut Sequencer) { - s.playing = false +fn stop_and_rewind (s: &mut Sequencer) -> Usually { + s.playing = false; + Ok(true) } -fn toggle_play (s: &mut Sequencer) { - s.playing = !s.playing +fn toggle_play (s: &mut Sequencer) -> Usually { + s.playing = !s.playing; + Ok(true) } -fn toggle_record (s: &mut Sequencer) { - s.recording = !s.recording +fn toggle_record (s: &mut Sequencer) -> Usually { + s.recording = !s.recording; + Ok(true) } -fn toggle_overdub (s: &mut Sequencer) { - s.overdub = !s.overdub +fn toggle_overdub (s: &mut Sequencer) -> Usually { + s.overdub = !s.overdub; + Ok(true) } -fn quantize_next (s: &mut Sequencer) { +fn quantize_next (s: &mut Sequencer) -> Usually { if s.resolution < 64 { - s.resolution = s.resolution * 2 + s.resolution = s.resolution * 2; } + Ok(true) } -fn quantize_prev (s: &mut Sequencer) { +fn quantize_prev (s: &mut Sequencer) -> Usually { if s.resolution > 1 { - s.resolution = s.resolution / 2 + s.resolution = s.resolution / 2; } + Ok(true) } #[cfg(test)] mod test { diff --git a/src/layout.rs b/src/layout.rs index 2362878e..98303869 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,51 +1,148 @@ use crate::prelude::*; +pub trait Focus { + fn focused (&self) -> Option<&Box>; + fn focused_mut (&mut self) -> Option<&mut Box>; + fn handle_focus (&mut self, event: &FocusEvent) -> Usually; +} + +enum FocusEvent { + Forward, + Backward, + Inward, + Outward, +} + +fn handle_focus ( + state: &mut T, + event: &AppEvent, + keymap: &[KeyBinding] +) -> Usually { + return Ok(if let Some(focused) = state.focused_mut() { + focused.handle(event) + } else { + Ok(false) + }? || handle_keymap( + state, event, keymap + )?) +} + pub struct Rows { focused: bool, focus: usize, items: Vec>, } +pub struct Columns { + focused: bool, + focus: usize, + items: Vec>, +} + impl Rows { pub fn new (focused: bool, items: Vec>) -> Self { Self { focused, focus: 0, items } } } -impl Device for Rows { - fn handle (&mut self, event: &AppEvent) -> Usually { - Ok(self.items[self.focus].handle(event)? || match event { - AppEvent::Input(event) => match event { - Event::Key(KeyEvent { code: KeyCode::Up, .. }) => { - if self.focus == 0 { - self.focus = self.items.len(); - } - self.focus = self.focus - 1; - true - }, - Event::Key(KeyEvent { code: KeyCode::Down, .. }) => { - self.focus = self.focus + 1; - if self.focus >= self.items.len() { - self.focus = 0; - } - true - }, - Event::Key(KeyEvent { code: KeyCode::Enter, .. }) => { - self.focused = true; - self.items[self.focus].handle(&AppEvent::Focus)?; - true - }, - Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => { - self.focused = false; - self.items[self.focus].handle(&AppEvent::Blur)?; - true - }, - _ => { - false +impl Columns { + pub fn new (focused: bool, items: Vec>) -> Self { + Self { focused, focus: 0, items } + } +} + +impl Focus for Rows { + fn focused (&self) -> Option<&Box> { + match self.focused { + true => self.items.get(self.focus), + false => None + } + } + fn focused_mut (&mut self) -> Option<&mut Box> { + match self.focused { + true => self.items.get_mut(self.focus), + false => None + } + } + fn handle_focus (&mut self, event: &FocusEvent) -> Usually { + match event { + FocusEvent::Backward => { + if self.focus == 0 { + self.focus = self.items.len(); + } + self.focus = self.focus - 1; + }, + FocusEvent::Forward => { + self.focus = self.focus + 1; + if self.focus >= self.items.len() { + self.focus = 0; } }, - _ => false - }) + FocusEvent::Inward => { + self.focused = true; + self.items[self.focus].handle(&AppEvent::Focus)?; + }, + FocusEvent::Outward => { + self.focused = false; + self.items[self.focus].handle(&AppEvent::Blur)?; + }, + }; + Ok(true) + } +} + +impl Focus for Columns { + fn focused (&self) -> Option<&Box> { + match self.focused { + true => self.items.get(self.focus), + false => None + } + } + fn focused_mut (&mut self) -> Option<&mut Box> { + match self.focused { + true => self.items.get_mut(self.focus), + false => None + } + } + fn handle_focus (&mut self, event: &FocusEvent) -> Usually { + match event { + FocusEvent::Backward => { + if self.focus == 0 { + self.focus = self.items.len(); + } + self.focus = self.focus - 1; + }, + FocusEvent::Forward => { + self.focus = self.focus + 1; + if self.focus >= self.items.len() { + self.focus = 0; + } + }, + FocusEvent::Inward => { + self.focused = true; + self.items[self.focus].handle(&AppEvent::Focus)?; + }, + FocusEvent::Outward => { + self.focused = false; + self.items[self.focus].handle(&AppEvent::Blur)?; + }, + }; + Ok(true) + } +} + +impl Device for Rows { + fn handle (&mut self, event: &AppEvent) -> Usually { + handle_focus(self, event, keymap!(Self { + [Up, NONE, "focus_up", "focus row above", + |s: &mut Self|s.handle_focus(&FocusEvent::Backward)], + [Down, NONE, "focus_down", "focus row below", + |s: &mut Self|s.handle_focus(&FocusEvent::Forward)], + [Enter, NONE, "focus_down", "focus row below", + |s: &mut Self|s.handle_focus(&FocusEvent::Inward)], + [Esc, NONE, "focus_down", "focus row below", + |s: &mut Self|s.handle_focus(&FocusEvent::Outward)] + })) } fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let mut w = 0u16; @@ -72,66 +169,18 @@ impl Device for Rows { } } -pub struct Columns { - focused: bool, - focus: usize, - items: Vec>, -} - -impl Columns { - pub fn new (focused: bool, items: Vec>) -> Self { - Self { focused, focus: 0, items } - } -} - impl Device for Columns { - fn handle (&mut self, event: &AppEvent) -> Usually { - let focused = match self.focused { - true => Some(self.items.get_mut(self.focus).unwrap()), - false => None - }; - - let handled = if let Some(item) = focused { - item.handle(event)? - } else { - false - }; - - if handled { - return Ok(true); - } - - Ok(match event { - AppEvent::Input(event) => match event { - Event::Key(KeyEvent { code: KeyCode::Left, .. }) => { - if self.focus == 0 { - self.focus = self.items.len(); - } - self.focus = self.focus - 1; - true - }, - Event::Key(KeyEvent { code: KeyCode::Right, .. }) => { - self.focus = self.focus + 1; - if self.focus >= self.items.len() { - self.focus = 0; - } - true - }, - Event::Key(KeyEvent { code: KeyCode::Enter, .. }) => { - self.focused = true; - self.items[self.focus].handle(&AppEvent::Focus)?; - true - }, - Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => { - self.focused = false; - self.items[self.focus].handle(&AppEvent::Blur)?; - true - }, - _ => false - }, - _ => false - }) + handle_focus(self, event, keymap!(Self { + [Left, NONE, "focus_up", "focus row above", + |s: &mut Self|s.handle_focus(&FocusEvent::Backward)], + [Right, NONE, "focus_down", "focus row below", + |s: &mut Self|s.handle_focus(&FocusEvent::Forward)], + [Enter, NONE, "focus_down", "focus row below", + |s: &mut Self|s.handle_focus(&FocusEvent::Inward)], + [Esc, NONE, "focus_down", "focus row below", + |s: &mut Self|s.handle_focus(&FocusEvent::Outward)] + })) } fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { diff --git a/src/prelude.rs b/src/prelude.rs index 453b5ac2..a57a1bba 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -90,20 +90,22 @@ pub type BoxedProcessHandler = Box Control + pub type Jack = AsyncClient>; +pub type KeyHandler = &'static dyn Fn(&mut T)->Usually; + pub type KeyBinding = ( - KeyCode, KeyModifiers, &'static str, &'static str, &'static dyn Fn(&mut T) + KeyCode, KeyModifiers, &'static str, &'static str, KeyHandler ); #[macro_export] macro_rules! key { - ($k:ident $(($char:literal))?, $m:ident, $n: literal, $d: literal, $f: ident) => { + ($k:ident $(($char:literal))?, $m:ident, $n: literal, $d: literal, $f: expr) => { (KeyCode::$k $(($char))?, KeyModifiers::$m, $n, $d, &$f) }; } #[macro_export] macro_rules! keymap { - ($T:ty { $([$k:ident $(($char:literal))?, $m:ident, $n: literal, $d: literal, $f: ident]),* }) => { + ($T:ty { $([$k:ident $(($char:literal))?, $m:ident, $n: literal, $d: literal, $f: expr]),* }) => { &[ - $((KeyCode::$k $(($char))?, KeyModifiers::$m, $n, $d, &$f as &'static dyn Fn(&mut $T))),* + $((KeyCode::$k $(($char))?, KeyModifiers::$m, $n, $d, &$f as KeyHandler<$T>)),* ] as &'static [KeyBinding<$T>] } } @@ -111,11 +113,11 @@ pub type KeyBinding = ( pub use crate::{key, keymap}; pub fn handle_keymap ( - commands: &[KeyBinding], state: &mut T, event: &AppEvent -) -> Result> { + state: &mut T, event: &AppEvent, keymap: &[KeyBinding], +) -> Usually { match event { AppEvent::Input(Event::Key(event)) => { - for (code, modifiers, _, _, command) in commands.iter() { + for (code, modifiers, _, _, command) in keymap.iter() { if *code == event.code && modifiers.bits() == event.modifiers.bits() { command(state); return Ok(true)