From c551f83d5cf50bc71ffc1b9ed9a3a1cbc18ec47c Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 9 Nov 2024 01:49:21 +0100 Subject: [PATCH] cmdsys: delegate handling --- crates/tek_core/src/command.rs | 8 ++++ crates/tek_core/src/focus.rs | 52 ++++++++++++++++------- crates/tek_sequencer/src/arranger.rs | 3 +- crates/tek_sequencer/src/arranger_cmd.rs | 38 +++++++---------- crates/tek_sequencer/src/sequencer.rs | 3 +- crates/tek_sequencer/src/sequencer_cmd.rs | 25 ++++------- 6 files changed, 72 insertions(+), 57 deletions(-) diff --git a/crates/tek_core/src/command.rs b/crates/tek_core/src/command.rs index c64352e6..ac1bb8e2 100644 --- a/crates/tek_core/src/command.rs +++ b/crates/tek_core/src/command.rs @@ -4,6 +4,14 @@ pub trait Command: Sized { fn translate (self, _: &S) -> Self { self } fn execute (self, state: &mut S) -> Perhaps; } +pub fn delegate , S> ( + wrap: impl Fn(C)->B, + state: &mut S, + cmd: C +) -> Perhaps { + Ok(cmd.execute(state)?.map(|x|wrap(x))) +} + pub trait MatchInput: Sized { fn match_input (state: &S, input: &E::Input) -> Option; } diff --git a/crates/tek_core/src/focus.rs b/crates/tek_core/src/focus.rs index 203da85b..138d89bc 100644 --- a/crates/tek_core/src/focus.rs +++ b/crates/tek_core/src/focus.rs @@ -1,27 +1,16 @@ use crate::*; -#[derive(Clone, PartialEq)] -pub enum FocusCommand { - Next, - Prev, - Up, - Down, - Left, - Right, - Enter, - Exit -} - -pub trait FocusGrid { - 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 { } 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 Command for FocusCommand { + fn execute (self, state: &mut F) -> Perhaps { + 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) + } } diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index a5d2b510..4e336c76 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -267,7 +267,8 @@ impl Arranger { } } /// Focus layout of arranger app -impl FocusGrid for Arranger { +impl FocusGrid for Arranger { + 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]] { &[ diff --git a/crates/tek_sequencer/src/arranger_cmd.rs b/crates/tek_sequencer/src/arranger_cmd.rs index 287d63bd..986bda3e 100644 --- a/crates/tek_sequencer/src/arranger_cmd.rs +++ b/crates/tek_sequencer/src/arranger_cmd.rs @@ -33,37 +33,31 @@ pub enum ArrangementCommand { GoLeft, GoRight, } + impl Command> for ArrangerCommand { fn execute (self, state: &mut Arranger) -> Perhaps { - 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 Command> for ArrangementCommand { diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index ce1debbf..a269810e 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -164,7 +164,8 @@ pub struct PhraseLength { Tick, } /// Focus layout of sequencer app -impl FocusGrid for Sequencer { +impl FocusGrid for Sequencer { + 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]] { &[ diff --git a/crates/tek_sequencer/src/sequencer_cmd.rs b/crates/tek_sequencer/src/sequencer_cmd.rs index ab3710eb..a723449e 100644 --- a/crates/tek_sequencer/src/sequencer_cmd.rs +++ b/crates/tek_sequencer/src/sequencer_cmd.rs @@ -73,27 +73,18 @@ pub enum PhraseEditorCommand { } impl Command> for SequencerCommand { fn execute (self, state: &mut Sequencer) -> Perhaps { - 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)