diff --git a/crates/tek_core/src/focus.rs b/crates/tek_core/src/focus.rs new file mode 100644 index 00000000..7b8e6492 --- /dev/null +++ b/crates/tek_core/src/focus.rs @@ -0,0 +1,70 @@ +use crate::*; + +pub trait Focus : Render + Handle { + fn focus (&self) -> usize; + fn focus_mut (&mut self) -> &mut usize; + fn focusable (&self) -> [&dyn Focusable;N]; + fn focusable_mut (&mut self) -> [&mut dyn Focusable;N]; + + fn focused (&self) -> &dyn Focusable { + let focus = self.focus(); + self.focusable()[focus] + } + fn focused_mut (&mut self) -> &mut dyn Focusable { + let focus = self.focus(); + self.focusable_mut()[focus] + } + fn focus_prev (&mut self) { + let focus = self.focus(); + let focus = if focus > 0 { N - 1 } else { focus - 1 }; + *self.focus_mut() = focus; + } + fn focus_next (&mut self) { + let focus = self.focus(); + let focus = if focus < N - 1 { focus + 1 } else { 0 }; + *self.focus_mut() = focus; + } +} + +pub trait Focusable: Render + Handle { + fn is_focused (&self) -> bool; + fn set_focused (&mut self, focused: bool); +} + +#[macro_export] macro_rules! focus { + ($struct:ident ($focus:ident) : $count:expr => [ + $($focusable:ident),* + ]) => { + impl Focus<$count> for $struct { + fn focus (&self) -> usize { + self.$focus + } + fn focus_mut (&mut self) -> &mut usize { + &mut self.$focus + } + fn focusable (&self) -> [&dyn Focusable;$count] { + [ + $(&self.$focusable as &dyn Focusable,)* + ] + } + fn focusable_mut (&mut self) -> [&mut dyn Focusable;2] { + [ + $(&mut self.$focusable as &mut dyn Focusable,)* + ] + } + } + } +} + +#[macro_export] macro_rules! focusable { + ($struct:ident ($focused:ident)) => { + impl Focusable for $struct { + fn is_focused (&self) -> bool { + self.$focused + } + fn set_focused (&mut self, focused: bool) { + self.$focused = focused + } + } + } +} diff --git a/crates/tek_core/src/lib.rs b/crates/tek_core/src/lib.rs index 19557d8b..3280395e 100644 --- a/crates/tek_core/src/lib.rs +++ b/crates/tek_core/src/lib.rs @@ -45,6 +45,7 @@ use crossterm::terminal::{ submod! { exit + focus handle handle_keymap jack_core diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index b4487892..7244b7d8 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -1,22 +1,20 @@ //! Clip launcher and arrangement editor. - use crate::*; -use tek_core::Direction; /// Represents the tracks and scenes of the composition. pub struct Arranger { /// Name of arranger - pub name: Arc>, + pub name: Arc>, /// Collection of tracks. - pub tracks: Vec, + pub tracks: Vec, /// Collection of scenes. - pub scenes: Vec, + pub scenes: Vec, /// Currently selected element. - pub selected: ArrangerFocus, + pub selected: ArrangerFocus, /// Display mode of arranger - pub mode: ArrangerViewMode, + pub mode: ArrangerViewMode, /// Slot for modal dialog displayed on top of app. - pub modal: Option>, + pub modal: Option>, } impl Arranger { diff --git a/crates/tek_sequencer/src/arranger_main.rs b/crates/tek_sequencer/src/arranger_main.rs index b6f33838..6ba98373 100644 --- a/crates/tek_sequencer/src/arranger_main.rs +++ b/crates/tek_sequencer/src/arranger_main.rs @@ -18,33 +18,7 @@ struct ArrangerStandalone { focus: usize, } -impl ArrangerStandalone { - fn focus_prev (&mut self) { - self.focus = if self.focus > 0 { 1 } else { self.focus - 1 }; - } - fn focus_next (&mut self) { - self.focus = if self.focus < 1 { self.focus + 1 } else { 0 }; - } - fn focused (&self) -> &dyn Render { - self.focusable()[self.focus] - } - fn focusable (&self) -> [&dyn Render;2] { - [ - &self.transport as &dyn Render, - &self.arranger as &dyn Render, - ] - } - fn focused_mut (&mut self) -> &mut dyn Handle { - let focus = self.focus; - self.focusable_mut()[focus] - } - fn focusable_mut (&mut self) -> [&mut dyn Handle;2] { - [ - &mut self.transport as &mut dyn Handle, - &mut self.arranger as &mut dyn Handle - ] - } -} +focus!(ArrangerStandalone (focus) : 2 => [ transport, arranger ]); #[derive(Debug, Parser)] #[command(version, about, long_about = None)]