cmdsys: delegate handling

This commit is contained in:
🪞👃🪞 2024-11-09 01:49:21 +01:00
parent 9b770c468f
commit c551f83d5c
6 changed files with 72 additions and 57 deletions

View file

@ -4,6 +4,14 @@ pub trait Command<S>: Sized {
fn translate (self, _: &S) -> Self { self } fn translate (self, _: &S) -> Self { self }
fn execute (self, state: &mut S) -> Perhaps<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 { pub trait MatchInput<E: Engine, S>: Sized {
fn match_input (state: &S, input: &E::Input) -> Option<Self>; fn match_input (state: &S, input: &E::Input) -> Option<Self>;
} }

View file

@ -1,27 +1,16 @@
use crate::*; use crate::*;
#[derive(Clone, PartialEq)] pub trait FocusGrid {
pub enum FocusCommand { type Item: Copy + PartialEq;
Next, fn layout (&self) -> &[&[Self::Item]];
Prev,
Up,
Down,
Left,
Right,
Enter,
Exit
}
pub trait FocusGrid<T: Copy + PartialEq> {
fn layout (&self) -> &[&[T]];
fn cursor (&self) -> (usize, usize); fn cursor (&self) -> (usize, usize);
fn cursor_mut (&mut self) -> &mut (usize, usize); fn cursor_mut (&mut self) -> &mut (usize, usize);
fn update_focus (&mut self) {} fn update_focus (&mut self) {}
fn focused (&self) -> &T { fn focused (&self) -> &Self::Item {
let (x, y) = self.cursor(); let (x, y) = self.cursor();
&self.layout()[y][x] &self.layout()[y][x]
} }
fn focus (&mut self, target: T) { fn focus (&mut self, target: Self::Item) {
while self.focused() != &target { while self.focused() != &target {
self.focus_next() self.focus_next()
} }
@ -90,4 +79,35 @@ pub trait FocusGrid<T: Copy + PartialEq> {
} }
self.update_focus(); 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)
}
} }

View file

@ -267,7 +267,8 @@ impl<E: Engine> Arranger<E> {
} }
} }
/// Focus layout of arranger app /// 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 (&self) -> (usize, usize) { self.focus_cursor }
fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor } fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor }
fn layout (&self) -> &[&[ArrangerFocus]] { &[ fn layout (&self) -> &[&[ArrangerFocus]] { &[

View file

@ -33,37 +33,31 @@ pub enum ArrangementCommand {
GoLeft, GoLeft,
GoRight, GoRight,
} }
impl<E: Engine> Command<Arranger<E>> for ArrangerCommand { impl<E: Engine> Command<Arranger<E>> for ArrangerCommand {
fn execute (self, state: &mut Arranger<E>) -> Perhaps<Self> { fn execute (self, state: &mut Arranger<E>) -> Perhaps<Self> {
use ArrangerCommand::*; let undo = match self {
use FocusCommand::*; Self::Focus(cmd) => {
match self { delegate(Self::Focus, state, cmd)
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!() },
}, },
Transport(cmd) => if let Some(ref transport) = state.transport { Self::Transport(cmd) => if let Some(ref transport) = state.transport {
return cmd.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) delegate(Self::Transport, &mut*transport.write().unwrap(), cmd)
} else {
Ok(None)
}, },
Phrases(cmd) => { Self::Phrases(cmd) => {
return cmd.execute(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases)) delegate(Self::Phrases, &mut*state.phrases.write().unwrap(), cmd)
}, },
Editor(cmd) => { Self::Editor(cmd) => {
return cmd.execute(&mut state.editor).map(|x|x.map(Editor)) delegate(Self::Editor, &mut state.editor, cmd)
}, },
Arrangement(cmd) => { Self::Arrangement(cmd) => {
return cmd.execute(&mut state.arrangement).map(|x|x.map(Arrangement)) delegate(Self::Arrangement, &mut state.arrangement, cmd)
}, },
} }?;
state.show_phrase(); state.show_phrase();
state.update_status(); state.update_status();
Ok(None) return Ok(undo);
} }
} }
impl<E: Engine> Command<Arrangement<E>> for ArrangementCommand { impl<E: Engine> Command<Arrangement<E>> for ArrangementCommand {

View file

@ -164,7 +164,8 @@ pub struct PhraseLength<E: Engine> {
Tick, Tick,
} }
/// Focus layout of sequencer app /// 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 (&self) -> (usize, usize) { self.focus_cursor }
fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor } fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor }
fn layout (&self) -> &[&[SequencerFocus]] { &[ fn layout (&self) -> &[&[SequencerFocus]] { &[

View file

@ -73,27 +73,18 @@ pub enum PhraseEditorCommand {
} }
impl<E: Engine> Command<Sequencer<E>> for SequencerCommand { impl<E: Engine> Command<Sequencer<E>> for SequencerCommand {
fn execute (self, state: &mut Sequencer<E>) -> Perhaps<Self> { fn execute (self, state: &mut Sequencer<E>) -> Perhaps<Self> {
use FocusCommand::*;
use SequencerCommand::*;
match self { match self {
Focus(command) => match command { Self::Focus(cmd) => {
Next => { state.focus_next(); }, return delegate(Self::Focus, state, cmd)
Prev => { state.focus_prev(); },
Up => { state.focus_up(); },
Down => { state.focus_down(); },
Left => { state.focus_left(); },
Right => { state.focus_right(); },
Enter => { unimplemented!() },
Exit => { unimplemented!() }
}, },
Transport(command) => if let Some(ref transport) = state.transport { Self::Transport(cmd) => if let Some(ref transport) = state.transport {
return command.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) return delegate(Self::Transport, &mut*transport.write().unwrap(), cmd)
}, },
Phrases(command) => { Self::Phrases(cmd) => {
return command.execute(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases)) return delegate(Self::Phrases, &mut*state.phrases.write().unwrap(), cmd)
}, },
Editor(command) => { Self::Editor(cmd) => {
return command.execute(&mut state.editor).map(|x|x.map(Editor)) return delegate(Self::Editor, &mut state.editor, cmd)
}, },
} }
Ok(None) Ok(None)