From 225c686db962d7be584f594c5f9d179817c6013d Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 20 Jun 2024 19:32:24 +0300 Subject: [PATCH] allow event bubbling --- src/device.rs | 21 ++++--- src/device/chain.rs | 4 +- src/device/looper.rs | 4 +- src/device/mixer.rs | 9 ++- src/device/plugin.rs | 4 +- src/device/sampler.rs | 4 +- src/device/sequencer.rs | 4 +- src/device/transport.rs | 4 +- src/layout.rs | 130 ++++++++++++++++++---------------------- src/prelude.rs | 6 +- 10 files changed, 90 insertions(+), 100 deletions(-) diff --git a/src/device.rs b/src/device.rs index b95e1bdd..afa0b805 100644 --- a/src/device.rs +++ b/src/device.rs @@ -88,25 +88,28 @@ pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box Usually<()> { - Ok(()) + // Returns Ok(true) if the device handled the event. + // This is the mechanism which allows nesting of components;. + fn handle (&mut self, _event: &AppEvent) -> Usually { + Ok(false) } + // Returns space used by component. + // This is insufficient but for the most basic dynamic layout algorithms. fn render (&self, _buffer: &mut Buffer, _area: Rect) -> Usually { Ok(Rect { x: 0, y: 0, width: 0, height: 0 }) } - fn process (&mut self, _client: Client, _scope: ProcessScope) {} } pub struct DynamicDevice { pub state: Arc>, pub render: MutexUsually + Send>>, - pub handle: ArcUsually<()> + Send>>>, + pub handle: ArcUsually + Send>>>, pub process: ArcControl + Send>>>, client: Option } impl Device for DynamicDevice { - fn handle (&mut self, event: &AppEvent) -> Usually<()> { + fn handle (&mut self, event: &AppEvent) -> Usually { self.handle.lock().unwrap()(&mut *self.state.lock().unwrap(), event) } fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { @@ -120,9 +123,9 @@ type DynamicProcessHandler = ClosureProcessHandler; impl DynamicDevice { fn new <'a, R, H, P> (render: R, handle: H, process: P, state: T) -> Self where - R: FnMut(&T, &mut Buffer, Rect)->Usually + Send + 'static, - H: FnMut(&mut T, &AppEvent) -> Result<(), Box> + Send + 'static, - P: FnMut(&mut T, &Client, &ProcessScope)->Control + Send + 'static, + R: FnMut(&T, &mut Buffer, Rect) -> Usually + Send + 'static, + H: FnMut(&mut T, &AppEvent) -> Usually + Send + 'static, + P: FnMut(&mut T, &Client, &ProcessScope) -> Control + Send + 'static, { Self { state: Arc::new(Mutex::new(state)), @@ -142,7 +145,7 @@ impl DynamicDevice { move|event|{ let mut state = state.lock().unwrap(); let mut handle = handle.lock().unwrap(); - handle(&mut state, &event).unwrap() + handle(&mut state, &event).unwrap(); } }) as Box), ClosureProcessHandler::new(Box::new({ let state = self.state.clone(); diff --git a/src/device/chain.rs b/src/device/chain.rs index fc3abf76..46ad0e8a 100644 --- a/src/device/chain.rs +++ b/src/device/chain.rs @@ -51,6 +51,6 @@ pub fn render (state: &Chain, buf: &mut Buffer, area: Rect) Ok(Rect { x: area.x, y: area.y, width: x, height: y }) } -pub fn handle (_: &mut Chain, _: &AppEvent) -> Result<(), Box> { - Ok(()) +pub fn handle (_: &mut Chain, _: &AppEvent) -> Usually { + Ok(false) } diff --git a/src/device/looper.rs b/src/device/looper.rs index c26cf3ca..5b0c9714 100644 --- a/src/device/looper.rs +++ b/src/device/looper.rs @@ -20,8 +20,8 @@ pub fn render (_: &Looper, _: &mut Buffer, _: Rect) -> Usually { Ok(Rect::default()) } -pub fn handle (_: &mut Looper, _: &AppEvent) -> Result<(), Box> { - Ok(()) +pub fn handle (_: &mut Looper, _: &AppEvent) -> Usually { + Ok(false) } pub const ACTIONS: [(&'static str, &'static str);1] = [ diff --git a/src/device/mixer.rs b/src/device/mixer.rs index 087232b0..1141c834 100644 --- a/src/device/mixer.rs +++ b/src/device/mixer.rs @@ -100,7 +100,7 @@ pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect) Ok(area) } -pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box> { +pub fn handle (state: &mut Mixer, event: &AppEvent) -> Usually { if let AppEvent::Input(crossterm::event::Event::Key(event)) = event { match event.code { @@ -112,6 +112,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box KeyCode::Down => { state.selected_track = (state.selected_track + 1) % state.tracks.len(); println!("{}", state.selected_track); + return Ok(true) }, KeyCode::Up => { if state.selected_track == 0 { @@ -120,6 +121,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box state.selected_track = state.selected_track - 1; } println!("{}", state.selected_track); + return Ok(true) }, KeyCode::Left => { if state.selected_column == 0 { @@ -127,6 +129,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box } else { state.selected_column = state.selected_column - 1; } + return Ok(true) }, KeyCode::Right => { if state.selected_column == 6 { @@ -134,6 +137,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box } else { state.selected_column = state.selected_column + 1; } + return Ok(true) }, _ => { println!("\n{event:?}"); @@ -141,8 +145,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box } } - - Ok(()) + Ok(false) } // TODO: diff --git a/src/device/plugin.rs b/src/device/plugin.rs index 50932815..9dd81f7e 100644 --- a/src/device/plugin.rs +++ b/src/device/plugin.rs @@ -31,6 +31,6 @@ pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, .. }: Rect) Ok(Rect { x, y, width: 40, height: 7 }) } -pub fn handle (_: &mut Plugin, _: &AppEvent) -> Result<(), Box> { - Ok(()) +pub fn handle (_: &mut Plugin, _: &AppEvent) -> Usually { + Ok(false) } diff --git a/src/device/sampler.rs b/src/device/sampler.rs index ed038b2e..ebb4c9c3 100644 --- a/src/device/sampler.rs +++ b/src/device/sampler.rs @@ -169,7 +169,8 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, .. }: Rect) //Ok(()) //} -pub fn handle (_: &mut Sampler, _: &AppEvent) -> Result<(), Box> { +pub fn handle (_: &mut Sampler, _: &AppEvent) -> Usually { + Ok(false) //if let Event::Input(crossterm::event::Event::Key(event)) = event { //match event.code { //KeyCode::Char('c') => { @@ -208,5 +209,4 @@ pub fn handle (_: &mut Sampler, _: &AppEvent) -> Result<(), Box> { //} //} //} - Ok(()) } diff --git a/src/device/sequencer.rs b/src/device/sequencer.rs index 24b8e545..5b8acb5e 100644 --- a/src/device/sequencer.rs +++ b/src/device/sequencer.rs @@ -173,7 +173,6 @@ fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { let (note0, note1) = s.note_axis; let pos = s.transport.query().unwrap().pos; let frame = pos.frame(); - let rate = pos.frame_rate().unwrap(); let usecs = s.timebase.frame_to_usec(frame as usize); let usec_per_step = s.timebase.usec_per_step(s.resolution as usize); let steps = usecs / usec_per_step; @@ -415,7 +414,7 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually Result<(), Box> { +pub fn handle (s: &mut Sequencer, event: &AppEvent) -> Usually { handle_keymap(COMMANDS, s, event) } @@ -450,7 +449,6 @@ fn nop (_: &mut Sequencer) { fn note_add (s: &mut Sequencer) { let pos = s.transport.query().unwrap().pos; let usecs = s.timebase.frame_to_usec(pos.frame() as usize); - let steps = usecs / s.timebase.usec_per_step(s.resolution as usize); let step = (s.time_axis.0 + s.time_cursor) as u32; let start = (step as usize * s.timebase.ppq() / s.resolution) as u32; let end = ((step + 1) as usize * s.timebase.ppq() / s.resolution) as u32; diff --git a/src/device/transport.rs b/src/device/transport.rs index de453eac..2981ef27 100644 --- a/src/device/transport.rs +++ b/src/device/transport.rs @@ -237,8 +237,8 @@ pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect) //Ok(()) //} -pub fn handle (_: &mut Transport, _: &AppEvent) -> Result<(), Box> { - Ok(()) +pub fn handle (_: &mut Transport, _: &AppEvent) -> Usually { + Ok(false) } pub const ACTIONS: [(&'static str, &'static str);4] = [ diff --git a/src/layout.rs b/src/layout.rs index 599fecaa..36c7f105 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -13,45 +13,39 @@ impl Rows { } impl Device for Rows { - fn handle (&mut self, event: &AppEvent) -> Usually<()> { - if !self.focused { - match event { - AppEvent::Input(Event::Key(KeyEvent { code: KeyCode::Esc, .. })) => { + fn handle (&mut self, event: &AppEvent) -> Usually { + 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 = false; + self.items[self.focus].handle(&AppEvent::Focus)?; + true + }, + Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => { self.focused = true; self.items[self.focus].handle(&AppEvent::Blur)?; - Ok(()) + true }, - _ => self.items[self.focus].handle(event) - } - } else { - 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; - }, - Event::Key(KeyEvent { code: KeyCode::Down, .. }) => { - self.focus = self.focus + 1; - if self.focus >= self.items.len() { - self.focus = 0; - } - }, - Event::Key(KeyEvent { code: KeyCode::Enter, .. }) => { - self.focused = false; - self.items[self.focus].handle(&AppEvent::Focus)?; - }, - Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => { - self.focused = true; - self.items[self.focus].handle(&AppEvent::Blur)?; - }, - _ => {} - }, - _ => {} - } - Ok(()) - } + _ => { + false + } + }, + _ => false + }) } fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let mut w = 0u16; @@ -91,45 +85,37 @@ impl Columns { } impl Device for Columns { - fn handle (&mut self, event: &AppEvent) -> Usually<()> { - if !self.focused { - match event { - AppEvent::Input(Event::Key(KeyEvent { code: KeyCode::Esc, .. })) => { + fn handle (&mut self, event: &AppEvent) -> Usually { + Ok(self.items[self.focus].handle(event)? || 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 = false; + self.items[self.focus].handle(&AppEvent::Focus)?; + true + }, + Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => { self.focused = true; self.items[self.focus].handle(&AppEvent::Blur)?; - Ok(()) + true }, - _ => self.items[self.focus].handle(event) - } - } else { - 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; - }, - Event::Key(KeyEvent { code: KeyCode::Right, .. }) => { - self.focus = self.focus + 1; - if self.focus >= self.items.len() { - self.focus = 0; - } - }, - Event::Key(KeyEvent { code: KeyCode::Enter, .. }) => { - self.focused = false; - self.items[self.focus].handle(&AppEvent::Focus)?; - }, - Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => { - self.focused = true; - self.items[self.focus].handle(&AppEvent::Blur)?; - }, - _ => {} - }, - _ => {} - } - Ok(()) - } + _ => false + }, + _ => false + }) } fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let mut w = 0u16; diff --git a/src/prelude.rs b/src/prelude.rs index a5a6da84..453b5ac2 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -112,17 +112,17 @@ pub use crate::{key, keymap}; pub fn handle_keymap ( commands: &[KeyBinding], state: &mut T, event: &AppEvent -) -> Result<(), Box> { +) -> Result> { match event { AppEvent::Input(Event::Key(event)) => { for (code, modifiers, _, _, command) in commands.iter() { if *code == event.code && modifiers.bits() == event.modifiers.bits() { command(state); - break + return Ok(true) } } }, _ => {} }; - Ok(()) + Ok(false) }