mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
cmdsys: delegate handling
This commit is contained in:
parent
9b770c468f
commit
c551f83d5c
6 changed files with 72 additions and 57 deletions
|
|
@ -4,6 +4,14 @@ pub trait Command<S>: Sized {
|
|||
fn translate (self, _: &S) -> Self { self }
|
||||
fn execute (self, state: &mut S) -> Perhaps<Self>;
|
||||
}
|
||||
pub fn delegate <B, C: Command<S>, S> (
|
||||
wrap: impl Fn(C)->B,
|
||||
state: &mut S,
|
||||
cmd: C
|
||||
) -> Perhaps<B> {
|
||||
Ok(cmd.execute(state)?.map(|x|wrap(x)))
|
||||
}
|
||||
|
||||
pub trait MatchInput<E: Engine, S>: Sized {
|
||||
fn match_input (state: &S, input: &E::Input) -> Option<Self>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,16 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum FocusCommand {
|
||||
Next,
|
||||
Prev,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Enter,
|
||||
Exit
|
||||
}
|
||||
|
||||
pub trait FocusGrid<T: Copy + PartialEq> {
|
||||
fn layout (&self) -> &[&[T]];
|
||||
pub trait FocusGrid {
|
||||
type Item: Copy + PartialEq;
|
||||
fn layout (&self) -> &[&[Self::Item]];
|
||||
fn cursor (&self) -> (usize, usize);
|
||||
fn cursor_mut (&mut self) -> &mut (usize, usize);
|
||||
fn update_focus (&mut self) {}
|
||||
fn focused (&self) -> &T {
|
||||
fn focused (&self) -> &Self::Item {
|
||||
let (x, y) = self.cursor();
|
||||
&self.layout()[y][x]
|
||||
}
|
||||
fn focus (&mut self, target: T) {
|
||||
fn focus (&mut self, target: Self::Item) {
|
||||
while self.focused() != &target {
|
||||
self.focus_next()
|
||||
}
|
||||
|
|
@ -90,4 +79,35 @@ pub trait FocusGrid<T: Copy + PartialEq> {
|
|||
}
|
||||
self.update_focus();
|
||||
}
|
||||
fn focus_enter (&mut self) {}
|
||||
fn focus_exit (&mut self) {}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum FocusCommand {
|
||||
Next,
|
||||
Prev,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Enter,
|
||||
Exit
|
||||
}
|
||||
|
||||
impl<F: FocusGrid> Command<F> for FocusCommand {
|
||||
fn execute (self, state: &mut F) -> Perhaps<FocusCommand> {
|
||||
use FocusCommand::*;
|
||||
match self {
|
||||
Next => { state.focus_next(); },
|
||||
Prev => { state.focus_prev(); },
|
||||
Up => { state.focus_up(); },
|
||||
Down => { state.focus_down(); },
|
||||
Left => { state.focus_left(); },
|
||||
Right => { state.focus_right(); },
|
||||
Enter => { state.focus_enter(); },
|
||||
Exit => { state.focus_exit(); },
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,7 +267,8 @@ impl<E: Engine> Arranger<E> {
|
|||
}
|
||||
}
|
||||
/// Focus layout of arranger app
|
||||
impl<E: Engine> FocusGrid<ArrangerFocus> for Arranger<E> {
|
||||
impl<E: Engine> FocusGrid for Arranger<E> {
|
||||
type Item = ArrangerFocus;
|
||||
fn cursor (&self) -> (usize, usize) { self.focus_cursor }
|
||||
fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor }
|
||||
fn layout (&self) -> &[&[ArrangerFocus]] { &[
|
||||
|
|
|
|||
|
|
@ -33,37 +33,31 @@ pub enum ArrangementCommand {
|
|||
GoLeft,
|
||||
GoRight,
|
||||
}
|
||||
|
||||
impl<E: Engine> Command<Arranger<E>> for ArrangerCommand {
|
||||
fn execute (self, state: &mut Arranger<E>) -> Perhaps<Self> {
|
||||
use ArrangerCommand::*;
|
||||
use FocusCommand::*;
|
||||
match self {
|
||||
Focus(command) => match command {
|
||||
Next => { state.focus_next(); },
|
||||
Prev => { state.focus_prev(); },
|
||||
Up => { state.focus_up(); },
|
||||
Down => { state.focus_down(); },
|
||||
Left => { state.focus_left(); },
|
||||
Right => { state.focus_right(); },
|
||||
Enter => { unimplemented!() },
|
||||
Exit => { unimplemented!() },
|
||||
let undo = match self {
|
||||
Self::Focus(cmd) => {
|
||||
delegate(Self::Focus, state, cmd)
|
||||
},
|
||||
Transport(cmd) => if let Some(ref transport) = state.transport {
|
||||
return cmd.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport))
|
||||
Self::Transport(cmd) => if let Some(ref transport) = state.transport {
|
||||
delegate(Self::Transport, &mut*transport.write().unwrap(), cmd)
|
||||
} else {
|
||||
Ok(None)
|
||||
},
|
||||
Phrases(cmd) => {
|
||||
return cmd.execute(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases))
|
||||
Self::Phrases(cmd) => {
|
||||
delegate(Self::Phrases, &mut*state.phrases.write().unwrap(), cmd)
|
||||
},
|
||||
Editor(cmd) => {
|
||||
return cmd.execute(&mut state.editor).map(|x|x.map(Editor))
|
||||
Self::Editor(cmd) => {
|
||||
delegate(Self::Editor, &mut state.editor, cmd)
|
||||
},
|
||||
Arrangement(cmd) => {
|
||||
return cmd.execute(&mut state.arrangement).map(|x|x.map(Arrangement))
|
||||
Self::Arrangement(cmd) => {
|
||||
delegate(Self::Arrangement, &mut state.arrangement, cmd)
|
||||
},
|
||||
}
|
||||
}?;
|
||||
state.show_phrase();
|
||||
state.update_status();
|
||||
Ok(None)
|
||||
return Ok(undo);
|
||||
}
|
||||
}
|
||||
impl<E: Engine> Command<Arrangement<E>> for ArrangementCommand {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ pub struct PhraseLength<E: Engine> {
|
|||
Tick,
|
||||
}
|
||||
/// Focus layout of sequencer app
|
||||
impl<E: Engine> FocusGrid<SequencerFocus> for Sequencer<E> {
|
||||
impl<E: Engine> FocusGrid for Sequencer<E> {
|
||||
type Item = SequencerFocus;
|
||||
fn cursor (&self) -> (usize, usize) { self.focus_cursor }
|
||||
fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor }
|
||||
fn layout (&self) -> &[&[SequencerFocus]] { &[
|
||||
|
|
|
|||
|
|
@ -73,27 +73,18 @@ pub enum PhraseEditorCommand {
|
|||
}
|
||||
impl<E: Engine> Command<Sequencer<E>> for SequencerCommand {
|
||||
fn execute (self, state: &mut Sequencer<E>) -> Perhaps<Self> {
|
||||
use FocusCommand::*;
|
||||
use SequencerCommand::*;
|
||||
match self {
|
||||
Focus(command) => match command {
|
||||
Next => { state.focus_next(); },
|
||||
Prev => { state.focus_prev(); },
|
||||
Up => { state.focus_up(); },
|
||||
Down => { state.focus_down(); },
|
||||
Left => { state.focus_left(); },
|
||||
Right => { state.focus_right(); },
|
||||
Enter => { unimplemented!() },
|
||||
Exit => { unimplemented!() }
|
||||
Self::Focus(cmd) => {
|
||||
return delegate(Self::Focus, state, cmd)
|
||||
},
|
||||
Transport(command) => if let Some(ref transport) = state.transport {
|
||||
return command.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport))
|
||||
Self::Transport(cmd) => if let Some(ref transport) = state.transport {
|
||||
return delegate(Self::Transport, &mut*transport.write().unwrap(), cmd)
|
||||
},
|
||||
Phrases(command) => {
|
||||
return command.execute(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases))
|
||||
Self::Phrases(cmd) => {
|
||||
return delegate(Self::Phrases, &mut*state.phrases.write().unwrap(), cmd)
|
||||
},
|
||||
Editor(command) => {
|
||||
return command.execute(&mut state.editor).map(|x|x.map(Editor))
|
||||
Self::Editor(cmd) => {
|
||||
return delegate(Self::Editor, &mut state.editor, cmd)
|
||||
},
|
||||
}
|
||||
Ok(None)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue