even wackier focus logic

This commit is contained in:
🪞👃🪞 2024-06-20 21:33:15 +03:00
parent ce1c28edb9
commit f5d02f9f08
3 changed files with 206 additions and 135 deletions

View file

@ -415,10 +415,10 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect
}
pub fn handle (s: &mut Sequencer, event: &AppEvent) -> Usually<bool> {
handle_keymap(COMMANDS, s, event)
handle_keymap(s, event, KEYMAP)
}
pub const COMMANDS: &'static [KeyBinding<Sequencer>] = keymap!(Sequencer {
pub const KEYMAP: &'static [KeyBinding<Sequencer>] = 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<Sequencer>] = keymap!(Sequencer {
[Char('s'), SHIFT, "sync", "Focus sync selector", nop]
});
fn nop (_: &mut Sequencer) {
fn nop (_: &mut Sequencer) -> Usually<bool> {
Ok(false)
}
fn note_add (s: &mut Sequencer) {
fn note_add (s: &mut Sequencer) -> Usually<bool> {
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<bool> {
Ok(true)
}
fn time_cursor_inc (s: &mut Sequencer) {
fn time_cursor_inc (s: &mut Sequencer) -> Usually<bool> {
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<bool> {
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<bool> {
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<bool> {
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<bool> {
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<bool> {
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<bool> {
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<bool> {
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<bool> {
//s.cursor.2 = s.cursor.2 + 1
Ok(true)
}
fn cursor_duration_dec (_: &mut Sequencer) {
fn cursor_duration_dec (_: &mut Sequencer) -> Usually<bool> {
//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<bool> {
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<bool> {
s.playing = false;
Ok(true)
}
fn toggle_play (s: &mut Sequencer) {
s.playing = !s.playing
fn toggle_play (s: &mut Sequencer) -> Usually<bool> {
s.playing = !s.playing;
Ok(true)
}
fn toggle_record (s: &mut Sequencer) {
s.recording = !s.recording
fn toggle_record (s: &mut Sequencer) -> Usually<bool> {
s.recording = !s.recording;
Ok(true)
}
fn toggle_overdub (s: &mut Sequencer) {
s.overdub = !s.overdub
fn toggle_overdub (s: &mut Sequencer) -> Usually<bool> {
s.overdub = !s.overdub;
Ok(true)
}
fn quantize_next (s: &mut Sequencer) {
fn quantize_next (s: &mut Sequencer) -> Usually<bool> {
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<bool> {
if s.resolution > 1 {
s.resolution = s.resolution / 2
s.resolution = s.resolution / 2;
}
Ok(true)
}
#[cfg(test)] mod test {

View file

@ -1,51 +1,148 @@
use crate::prelude::*;
pub trait Focus {
fn focused (&self) -> Option<&Box<dyn Device>>;
fn focused_mut (&mut self) -> Option<&mut Box<dyn Device>>;
fn handle_focus (&mut self, event: &FocusEvent) -> Usually<bool>;
}
enum FocusEvent {
Forward,
Backward,
Inward,
Outward,
}
fn handle_focus <T: Device + Focus> (
state: &mut T,
event: &AppEvent,
keymap: &[KeyBinding<T>]
) -> Usually<bool> {
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<Box<dyn Device>>,
}
pub struct Columns {
focused: bool,
focus: usize,
items: Vec<Box<dyn Device>>,
}
impl Rows {
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
Self { focused, focus: 0, items }
}
}
impl Device for Rows {
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
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<Box<dyn Device>>) -> Self {
Self { focused, focus: 0, items }
}
}
impl Focus for Rows {
fn focused (&self) -> Option<&Box<dyn Device>> {
match self.focused {
true => self.items.get(self.focus),
false => None
}
}
fn focused_mut (&mut self) -> Option<&mut Box<dyn Device>> {
match self.focused {
true => self.items.get_mut(self.focus),
false => None
}
}
fn handle_focus (&mut self, event: &FocusEvent) -> Usually<bool> {
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<dyn Device>> {
match self.focused {
true => self.items.get(self.focus),
false => None
}
}
fn focused_mut (&mut self) -> Option<&mut Box<dyn Device>> {
match self.focused {
true => self.items.get_mut(self.focus),
false => None
}
}
fn handle_focus (&mut self, event: &FocusEvent) -> Usually<bool> {
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<bool> {
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<Rect> {
let mut w = 0u16;
@ -72,66 +169,18 @@ impl Device for Rows {
}
}
pub struct Columns {
focused: bool,
focus: usize,
items: Vec<Box<dyn Device>>,
}
impl Columns {
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
Self { focused, focus: 0, items }
}
}
impl Device for Columns {
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
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<Rect> {

View file

@ -90,20 +90,22 @@ pub type BoxedProcessHandler = Box<dyn FnMut(&Client, &ProcessScope)-> Control +
pub type Jack<N> = AsyncClient<N, ClosureProcessHandler<BoxedProcessHandler>>;
pub type KeyHandler<T> = &'static dyn Fn(&mut T)->Usually<bool>;
pub type KeyBinding<T> = (
KeyCode, KeyModifiers, &'static str, &'static str, &'static dyn Fn(&mut T)
KeyCode, KeyModifiers, &'static str, &'static str, KeyHandler<T>
);
#[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<T> = (
pub use crate::{key, keymap};
pub fn handle_keymap <T> (
commands: &[KeyBinding<T>], state: &mut T, event: &AppEvent
) -> Result<bool, Box<dyn Error>> {
state: &mut T, event: &AppEvent, keymap: &[KeyBinding<T>],
) -> Usually<bool> {
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)