allow event bubbling

This commit is contained in:
🪞👃🪞 2024-06-20 19:32:24 +03:00
parent f77c84a99c
commit 225c686db9
10 changed files with 90 additions and 100 deletions

View file

@ -88,25 +88,28 @@ pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box<dyn E
} }
pub trait Device: Send + Sync { pub trait Device: Send + Sync {
fn handle (&mut self, _event: &AppEvent) -> Usually<()> { // Returns Ok(true) if the device handled the event.
Ok(()) // This is the mechanism which allows nesting of components;.
fn handle (&mut self, _event: &AppEvent) -> Usually<bool> {
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<Rect> { fn render (&self, _buffer: &mut Buffer, _area: Rect) -> Usually<Rect> {
Ok(Rect { x: 0, y: 0, width: 0, height: 0 }) Ok(Rect { x: 0, y: 0, width: 0, height: 0 })
} }
fn process (&mut self, _client: Client, _scope: ProcessScope) {}
} }
pub struct DynamicDevice<T> { pub struct DynamicDevice<T> {
pub state: Arc<Mutex<T>>, pub state: Arc<Mutex<T>>,
pub render: Mutex<Box<dyn FnMut(&T, &mut Buffer, Rect)->Usually<Rect> + Send>>, pub render: Mutex<Box<dyn FnMut(&T, &mut Buffer, Rect)->Usually<Rect> + Send>>,
pub handle: Arc<Mutex<Box<dyn FnMut(&mut T, &AppEvent)->Usually<()> + Send>>>, pub handle: Arc<Mutex<Box<dyn FnMut(&mut T, &AppEvent)->Usually<bool> + Send>>>,
pub process: Arc<Mutex<Box<dyn FnMut(&mut T, &Client, &ProcessScope)->Control + Send>>>, pub process: Arc<Mutex<Box<dyn FnMut(&mut T, &Client, &ProcessScope)->Control + Send>>>,
client: Option<DynamicAsyncClient> client: Option<DynamicAsyncClient>
} }
impl<T: Send + Sync> Device for DynamicDevice<T> { impl<T: Send + Sync> Device for DynamicDevice<T> {
fn handle (&mut self, event: &AppEvent) -> Usually<()> { fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
self.handle.lock().unwrap()(&mut *self.state.lock().unwrap(), event) self.handle.lock().unwrap()(&mut *self.state.lock().unwrap(), event)
} }
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
@ -120,9 +123,9 @@ type DynamicProcessHandler = ClosureProcessHandler<BoxedProcessHandler>;
impl<T: Send + Sync + 'static> DynamicDevice<T> { impl<T: Send + Sync + 'static> DynamicDevice<T> {
fn new <'a, R, H, P> (render: R, handle: H, process: P, state: T) -> Self where fn new <'a, R, H, P> (render: R, handle: H, process: P, state: T) -> Self where
R: FnMut(&T, &mut Buffer, Rect)->Usually<Rect> + Send + 'static, R: FnMut(&T, &mut Buffer, Rect) -> Usually<Rect> + Send + 'static,
H: FnMut(&mut T, &AppEvent) -> Result<(), Box<dyn Error>> + Send + 'static, H: FnMut(&mut T, &AppEvent) -> Usually<bool> + Send + 'static,
P: FnMut(&mut T, &Client, &ProcessScope)->Control + Send + 'static, P: FnMut(&mut T, &Client, &ProcessScope) -> Control + Send + 'static,
{ {
Self { Self {
state: Arc::new(Mutex::new(state)), state: Arc::new(Mutex::new(state)),
@ -142,7 +145,7 @@ impl<T: Send + Sync + 'static> DynamicDevice<T> {
move|event|{ move|event|{
let mut state = state.lock().unwrap(); let mut state = state.lock().unwrap();
let mut handle = handle.lock().unwrap(); let mut handle = handle.lock().unwrap();
handle(&mut state, &event).unwrap() handle(&mut state, &event).unwrap();
} }
}) as Box<dyn Fn(AppEvent) + Send + Sync>), ClosureProcessHandler::new(Box::new({ }) as Box<dyn Fn(AppEvent) + Send + Sync>), ClosureProcessHandler::new(Box::new({
let state = self.state.clone(); let state = self.state.clone();

View file

@ -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 }) Ok(Rect { x: area.x, y: area.y, width: x, height: y })
} }
pub fn handle (_: &mut Chain, _: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (_: &mut Chain, _: &AppEvent) -> Usually<bool> {
Ok(()) Ok(false)
} }

View file

@ -20,8 +20,8 @@ pub fn render (_: &Looper, _: &mut Buffer, _: Rect) -> Usually<Rect> {
Ok(Rect::default()) Ok(Rect::default())
} }
pub fn handle (_: &mut Looper, _: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (_: &mut Looper, _: &AppEvent) -> Usually<bool> {
Ok(()) Ok(false)
} }
pub const ACTIONS: [(&'static str, &'static str);1] = [ pub const ACTIONS: [(&'static str, &'static str);1] = [

View file

@ -100,7 +100,7 @@ pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect)
Ok(area) Ok(area)
} }
pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (state: &mut Mixer, event: &AppEvent) -> Usually<bool> {
if let AppEvent::Input(crossterm::event::Event::Key(event)) = event { if let AppEvent::Input(crossterm::event::Event::Key(event)) = event {
match event.code { match event.code {
@ -112,6 +112,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>
KeyCode::Down => { KeyCode::Down => {
state.selected_track = (state.selected_track + 1) % state.tracks.len(); state.selected_track = (state.selected_track + 1) % state.tracks.len();
println!("{}", state.selected_track); println!("{}", state.selected_track);
return Ok(true)
}, },
KeyCode::Up => { KeyCode::Up => {
if state.selected_track == 0 { if state.selected_track == 0 {
@ -120,6 +121,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>
state.selected_track = state.selected_track - 1; state.selected_track = state.selected_track - 1;
} }
println!("{}", state.selected_track); println!("{}", state.selected_track);
return Ok(true)
}, },
KeyCode::Left => { KeyCode::Left => {
if state.selected_column == 0 { if state.selected_column == 0 {
@ -127,6 +129,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>
} else { } else {
state.selected_column = state.selected_column - 1; state.selected_column = state.selected_column - 1;
} }
return Ok(true)
}, },
KeyCode::Right => { KeyCode::Right => {
if state.selected_column == 6 { if state.selected_column == 6 {
@ -134,6 +137,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>
} else { } else {
state.selected_column = state.selected_column + 1; state.selected_column = state.selected_column + 1;
} }
return Ok(true)
}, },
_ => { _ => {
println!("\n{event:?}"); println!("\n{event:?}");
@ -141,8 +145,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>
} }
} }
Ok(false)
Ok(())
} }
// TODO: // TODO:

View file

@ -31,6 +31,6 @@ pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, .. }: Rect)
Ok(Rect { x, y, width: 40, height: 7 }) Ok(Rect { x, y, width: 40, height: 7 })
} }
pub fn handle (_: &mut Plugin, _: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (_: &mut Plugin, _: &AppEvent) -> Usually<bool> {
Ok(()) Ok(false)
} }

View file

@ -169,7 +169,8 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, .. }: Rect)
//Ok(()) //Ok(())
//} //}
pub fn handle (_: &mut Sampler, _: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (_: &mut Sampler, _: &AppEvent) -> Usually<bool> {
Ok(false)
//if let Event::Input(crossterm::event::Event::Key(event)) = event { //if let Event::Input(crossterm::event::Event::Key(event)) = event {
//match event.code { //match event.code {
//KeyCode::Char('c') => { //KeyCode::Char('c') => {
@ -208,5 +209,4 @@ pub fn handle (_: &mut Sampler, _: &AppEvent) -> Result<(), Box<dyn Error>> {
//} //}
//} //}
//} //}
Ok(())
} }

View file

@ -173,7 +173,6 @@ fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let (note0, note1) = s.note_axis; let (note0, note1) = s.note_axis;
let pos = s.transport.query().unwrap().pos; let pos = s.transport.query().unwrap().pos;
let frame = pos.frame(); let frame = pos.frame();
let rate = pos.frame_rate().unwrap();
let usecs = s.timebase.frame_to_usec(frame as usize); let usecs = s.timebase.frame_to_usec(frame as usize);
let usec_per_step = s.timebase.usec_per_step(s.resolution as usize); let usec_per_step = s.timebase.usec_per_step(s.resolution as usize);
let steps = usecs / usec_per_step; let steps = usecs / usec_per_step;
@ -415,7 +414,7 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect
Ok(Rect { x, y, width: time1 - time0 + 6, height}) Ok(Rect { x, y, width: time1 - time0 + 6, height})
} }
pub fn handle (s: &mut Sequencer, event: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (s: &mut Sequencer, event: &AppEvent) -> Usually<bool> {
handle_keymap(COMMANDS, s, event) handle_keymap(COMMANDS, s, event)
} }
@ -450,7 +449,6 @@ fn nop (_: &mut Sequencer) {
fn note_add (s: &mut Sequencer) { fn note_add (s: &mut Sequencer) {
let pos = s.transport.query().unwrap().pos; let pos = s.transport.query().unwrap().pos;
let usecs = s.timebase.frame_to_usec(pos.frame() as usize); 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 step = (s.time_axis.0 + s.time_cursor) as u32;
let start = (step as usize * s.timebase.ppq() / s.resolution) 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; let end = ((step + 1) as usize * s.timebase.ppq() / s.resolution) as u32;

View file

@ -237,8 +237,8 @@ pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect)
//Ok(()) //Ok(())
//} //}
pub fn handle (_: &mut Transport, _: &AppEvent) -> Result<(), Box<dyn Error>> { pub fn handle (_: &mut Transport, _: &AppEvent) -> Usually<bool> {
Ok(()) Ok(false)
} }
pub const ACTIONS: [(&'static str, &'static str);4] = [ pub const ACTIONS: [(&'static str, &'static str);4] = [

View file

@ -13,45 +13,39 @@ impl Rows {
} }
impl Device for Rows { impl Device for Rows {
fn handle (&mut self, event: &AppEvent) -> Usually<()> { fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
if !self.focused { Ok(self.items[self.focus].handle(event)? || match event {
match event { AppEvent::Input(event) => match event {
AppEvent::Input(Event::Key(KeyEvent { code: KeyCode::Esc, .. })) => { 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.focused = true;
self.items[self.focus].handle(&AppEvent::Blur)?; self.items[self.focus].handle(&AppEvent::Blur)?;
Ok(()) true
}, },
_ => self.items[self.focus].handle(event) _ => {
} false
} else { }
match event { },
AppEvent::Input(event) => match event { _ => false
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(())
}
} }
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let mut w = 0u16; let mut w = 0u16;
@ -91,45 +85,37 @@ impl Columns {
} }
impl Device for Columns { impl Device for Columns {
fn handle (&mut self, event: &AppEvent) -> Usually<()> { fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
if !self.focused { Ok(self.items[self.focus].handle(event)? || match event {
match event { AppEvent::Input(event) => match event {
AppEvent::Input(Event::Key(KeyEvent { code: KeyCode::Esc, .. })) => { 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.focused = true;
self.items[self.focus].handle(&AppEvent::Blur)?; self.items[self.focus].handle(&AppEvent::Blur)?;
Ok(()) true
}, },
_ => self.items[self.focus].handle(event) _ => false
} },
} else { _ => false
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(())
}
} }
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let mut w = 0u16; let mut w = 0u16;

View file

@ -112,17 +112,17 @@ pub use crate::{key, keymap};
pub fn handle_keymap <T> ( pub fn handle_keymap <T> (
commands: &[KeyBinding<T>], state: &mut T, event: &AppEvent commands: &[KeyBinding<T>], state: &mut T, event: &AppEvent
) -> Result<(), Box<dyn Error>> { ) -> Result<bool, Box<dyn Error>> {
match event { match event {
AppEvent::Input(Event::Key(event)) => { AppEvent::Input(Event::Key(event)) => {
for (code, modifiers, _, _, command) in commands.iter() { for (code, modifiers, _, _, command) in commands.iter() {
if *code == event.code && modifiers.bits() == event.modifiers.bits() { if *code == event.code && modifiers.bits() == event.modifiers.bits() {
command(state); command(state);
break return Ok(true)
} }
} }
}, },
_ => {} _ => {}
}; };
Ok(()) Ok(false)
} }