mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +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> {
|
||||
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 {
|
||||
|
|
|
|||
229
src/layout.rs
229
src/layout.rs
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue