mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
even wackier focus logic
This commit is contained in:
parent
ce1c28edb9
commit
f5d02f9f08
3 changed files with 206 additions and 135 deletions
|
|
@ -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> {
|
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],
|
[Up, NONE, "cursor_up", "move cursor up", cursor_up],
|
||||||
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
|
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
|
||||||
[Left, NONE, "cursor_left", "move cursor left", cursor_left],
|
[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]
|
[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 pos = s.transport.query().unwrap().pos;
|
||||||
let usecs = s.timebase.frame_to_usec(pos.frame() as usize);
|
let usecs = s.timebase.frame_to_usec(pos.frame() as usize);
|
||||||
let step = (s.time_axis.0 + s.time_cursor) as u32;
|
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());
|
s.sequence.get_mut(&end).unwrap().push(note_off.clone());
|
||||||
} else {
|
} else {
|
||||||
s.sequence.insert(end, vec![note_off]);
|
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;
|
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;
|
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;
|
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;
|
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 {
|
match s.mode {
|
||||||
SequencerView::Vertical => time_cursor_dec(s),
|
SequencerView::Vertical => time_cursor_dec(s),
|
||||||
SequencerView::Horizontal => note_cursor_dec(s),
|
SequencerView::Horizontal => note_cursor_dec(s),
|
||||||
_ => unimplemented!()
|
_ => unimplemented!()
|
||||||
}
|
};
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn cursor_down (s: &mut Sequencer) {
|
fn cursor_down (s: &mut Sequencer) -> Usually<bool> {
|
||||||
match s.mode {
|
match s.mode {
|
||||||
SequencerView::Vertical => time_cursor_inc(s),
|
SequencerView::Vertical => time_cursor_inc(s),
|
||||||
SequencerView::Horizontal => note_cursor_inc(s),
|
SequencerView::Horizontal => note_cursor_inc(s),
|
||||||
_ => unimplemented!()
|
_ => unimplemented!()
|
||||||
}
|
};
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn cursor_left (s: &mut Sequencer) {
|
fn cursor_left (s: &mut Sequencer) -> Usually<bool> {
|
||||||
match s.mode {
|
match s.mode {
|
||||||
SequencerView::Vertical => note_cursor_dec(s),
|
SequencerView::Vertical => note_cursor_dec(s),
|
||||||
SequencerView::Horizontal => time_cursor_dec(s),
|
SequencerView::Horizontal => time_cursor_dec(s),
|
||||||
_ => unimplemented!()
|
_ => unimplemented!()
|
||||||
}
|
};
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn cursor_right (s: &mut Sequencer) {
|
fn cursor_right (s: &mut Sequencer) -> Usually<bool> {
|
||||||
match s.mode {
|
match s.mode {
|
||||||
SequencerView::Vertical => note_cursor_inc(s),
|
SequencerView::Vertical => note_cursor_inc(s),
|
||||||
SequencerView::Horizontal => time_cursor_inc(s),
|
SequencerView::Horizontal => time_cursor_inc(s),
|
||||||
_ => unimplemented!()
|
_ => unimplemented!()
|
||||||
}
|
};
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn cursor_duration_inc (_: &mut Sequencer) {
|
fn cursor_duration_inc (_: &mut Sequencer) -> Usually<bool> {
|
||||||
//s.cursor.2 = s.cursor.2 + 1
|
//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 }
|
//if s.cursor.2 > 0 { s.cursor.2 = s.cursor.2 - 1 }
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn mode_next (s: &mut Sequencer) {
|
fn mode_next (s: &mut Sequencer) -> Usually<bool> {
|
||||||
s.mode = s.mode.next()
|
s.mode = s.mode.next();
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
impl SequencerView {
|
impl SequencerView {
|
||||||
fn next (&self) -> Self {
|
fn next (&self) -> Self {
|
||||||
|
|
@ -530,27 +544,33 @@ impl SequencerView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn stop_and_rewind (s: &mut Sequencer) {
|
fn stop_and_rewind (s: &mut Sequencer) -> Usually<bool> {
|
||||||
s.playing = false
|
s.playing = false;
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn toggle_play (s: &mut Sequencer) {
|
fn toggle_play (s: &mut Sequencer) -> Usually<bool> {
|
||||||
s.playing = !s.playing
|
s.playing = !s.playing;
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn toggle_record (s: &mut Sequencer) {
|
fn toggle_record (s: &mut Sequencer) -> Usually<bool> {
|
||||||
s.recording = !s.recording
|
s.recording = !s.recording;
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn toggle_overdub (s: &mut Sequencer) {
|
fn toggle_overdub (s: &mut Sequencer) -> Usually<bool> {
|
||||||
s.overdub = !s.overdub
|
s.overdub = !s.overdub;
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn quantize_next (s: &mut Sequencer) {
|
fn quantize_next (s: &mut Sequencer) -> Usually<bool> {
|
||||||
if s.resolution < 64 {
|
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 {
|
if s.resolution > 1 {
|
||||||
s.resolution = s.resolution / 2
|
s.resolution = s.resolution / 2;
|
||||||
}
|
}
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] mod test {
|
#[cfg(test)] mod test {
|
||||||
|
|
|
||||||
197
src/layout.rs
197
src/layout.rs
|
|
@ -1,51 +1,148 @@
|
||||||
use crate::prelude::*;
|
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 {
|
pub struct Rows {
|
||||||
focused: bool,
|
focused: bool,
|
||||||
focus: usize,
|
focus: usize,
|
||||||
items: Vec<Box<dyn Device>>,
|
items: Vec<Box<dyn Device>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Columns {
|
||||||
|
focused: bool,
|
||||||
|
focus: usize,
|
||||||
|
items: Vec<Box<dyn Device>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Rows {
|
impl Rows {
|
||||||
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
|
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
|
||||||
Self { focused, focus: 0, items }
|
Self { focused, focus: 0, items }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device for Rows {
|
impl Columns {
|
||||||
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
|
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
|
||||||
Ok(self.items[self.focus].handle(event)? || match event {
|
Self { focused, focus: 0, items }
|
||||||
AppEvent::Input(event) => match event {
|
}
|
||||||
Event::Key(KeyEvent { code: KeyCode::Up, .. }) => {
|
}
|
||||||
|
|
||||||
|
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 {
|
if self.focus == 0 {
|
||||||
self.focus = self.items.len();
|
self.focus = self.items.len();
|
||||||
}
|
}
|
||||||
self.focus = self.focus - 1;
|
self.focus = self.focus - 1;
|
||||||
true
|
|
||||||
},
|
},
|
||||||
Event::Key(KeyEvent { code: KeyCode::Down, .. }) => {
|
FocusEvent::Forward => {
|
||||||
self.focus = self.focus + 1;
|
self.focus = self.focus + 1;
|
||||||
if self.focus >= self.items.len() {
|
if self.focus >= self.items.len() {
|
||||||
self.focus = 0;
|
self.focus = 0;
|
||||||
}
|
}
|
||||||
true
|
|
||||||
},
|
},
|
||||||
Event::Key(KeyEvent { code: KeyCode::Enter, .. }) => {
|
FocusEvent::Inward => {
|
||||||
self.focused = true;
|
self.focused = true;
|
||||||
self.items[self.focus].handle(&AppEvent::Focus)?;
|
self.items[self.focus].handle(&AppEvent::Focus)?;
|
||||||
true
|
|
||||||
},
|
},
|
||||||
Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => {
|
FocusEvent::Outward => {
|
||||||
self.focused = false;
|
self.focused = false;
|
||||||
self.items[self.focus].handle(&AppEvent::Blur)?;
|
self.items[self.focus].handle(&AppEvent::Blur)?;
|
||||||
true
|
|
||||||
},
|
},
|
||||||
_ => {
|
};
|
||||||
false
|
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;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => 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 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> {
|
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||||
let mut w = 0u16;
|
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 {
|
impl Device for Columns {
|
||||||
|
|
||||||
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
|
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
|
||||||
let focused = match self.focused {
|
handle_focus(self, event, keymap!(Self {
|
||||||
true => Some(self.items.get_mut(self.focus).unwrap()),
|
[Left, NONE, "focus_up", "focus row above",
|
||||||
false => None
|
|s: &mut Self|s.handle_focus(&FocusEvent::Backward)],
|
||||||
};
|
[Right, NONE, "focus_down", "focus row below",
|
||||||
|
|s: &mut Self|s.handle_focus(&FocusEvent::Forward)],
|
||||||
let handled = if let Some(item) = focused {
|
[Enter, NONE, "focus_down", "focus row below",
|
||||||
item.handle(event)?
|
|s: &mut Self|s.handle_focus(&FocusEvent::Inward)],
|
||||||
} else {
|
[Esc, NONE, "focus_down", "focus row below",
|
||||||
false
|
|s: &mut Self|s.handle_focus(&FocusEvent::Outward)]
|
||||||
};
|
}))
|
||||||
|
|
||||||
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
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||||
|
|
|
||||||
|
|
@ -90,20 +90,22 @@ pub type BoxedProcessHandler = Box<dyn FnMut(&Client, &ProcessScope)-> Control +
|
||||||
|
|
||||||
pub type Jack<N> = AsyncClient<N, ClosureProcessHandler<BoxedProcessHandler>>;
|
pub type Jack<N> = AsyncClient<N, ClosureProcessHandler<BoxedProcessHandler>>;
|
||||||
|
|
||||||
|
pub type KeyHandler<T> = &'static dyn Fn(&mut T)->Usually<bool>;
|
||||||
|
|
||||||
pub type KeyBinding<T> = (
|
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 {
|
#[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)
|
(KeyCode::$k $(($char))?, KeyModifiers::$m, $n, $d, &$f)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export] macro_rules! keymap {
|
#[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>]
|
] as &'static [KeyBinding<$T>]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,11 +113,11 @@ pub type KeyBinding<T> = (
|
||||||
pub use crate::{key, keymap};
|
pub use crate::{key, keymap};
|
||||||
|
|
||||||
pub fn handle_keymap <T> (
|
pub fn handle_keymap <T> (
|
||||||
commands: &[KeyBinding<T>], state: &mut T, event: &AppEvent
|
state: &mut T, event: &AppEvent, keymap: &[KeyBinding<T>],
|
||||||
) -> Result<bool, Box<dyn Error>> {
|
) -> Usually<bool> {
|
||||||
match event {
|
match event {
|
||||||
AppEvent::Input(Event::Key(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() {
|
if *code == event.code && modifiers.bits() == event.modifiers.bits() {
|
||||||
command(state);
|
command(state);
|
||||||
return Ok(true)
|
return Ok(true)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue