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 {
fn handle (&mut self, _event: &AppEvent) -> 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<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> {
Ok(Rect { x: 0, y: 0, width: 0, height: 0 })
}
fn process (&mut self, _client: Client, _scope: ProcessScope) {}
}
pub struct DynamicDevice<T> {
pub state: Arc<Mutex<T>>,
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>>>,
client: Option<DynamicAsyncClient>
}
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)
}
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> {
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,
H: FnMut(&mut T, &AppEvent) -> Result<(), Box<dyn Error>> + Send + 'static,
P: FnMut(&mut T, &Client, &ProcessScope)->Control + Send + 'static,
R: FnMut(&T, &mut Buffer, Rect) -> Usually<Rect> + Send + 'static,
H: FnMut(&mut T, &AppEvent) -> Usually<bool> + Send + 'static,
P: FnMut(&mut T, &Client, &ProcessScope) -> Control + Send + 'static,
{
Self {
state: Arc::new(Mutex::new(state)),
@ -142,7 +145,7 @@ impl<T: Send + Sync + 'static> DynamicDevice<T> {
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<dyn Fn(AppEvent) + Send + Sync>), ClosureProcessHandler::new(Box::new({
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 })
}
pub fn handle (_: &mut Chain, _: &AppEvent) -> Result<(), Box<dyn Error>> {
Ok(())
pub fn handle (_: &mut Chain, _: &AppEvent) -> Usually<bool> {
Ok(false)
}

View file

@ -20,8 +20,8 @@ pub fn render (_: &Looper, _: &mut Buffer, _: Rect) -> Usually<Rect> {
Ok(Rect::default())
}
pub fn handle (_: &mut Looper, _: &AppEvent) -> Result<(), Box<dyn Error>> {
Ok(())
pub fn handle (_: &mut Looper, _: &AppEvent) -> Usually<bool> {
Ok(false)
}
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)
}
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 {
match event.code {
@ -112,6 +112,7 @@ pub fn handle (state: &mut Mixer, event: &AppEvent) -> Result<(), Box<dyn Error>
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<dyn Error>
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<dyn Error>
} 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<dyn Error>
} 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<dyn Error>
}
}
Ok(())
Ok(false)
}
// 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 })
}
pub fn handle (_: &mut Plugin, _: &AppEvent) -> Result<(), Box<dyn Error>> {
Ok(())
pub fn handle (_: &mut Plugin, _: &AppEvent) -> Usually<bool> {
Ok(false)
}

View file

@ -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<dyn Error>> {
pub fn handle (_: &mut Sampler, _: &AppEvent) -> Usually<bool> {
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<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 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<Rect
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)
}
@ -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;

View file

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

View file

@ -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, .. })) => {
self.focused = true;
self.items[self.focus].handle(&AppEvent::Blur)?;
Ok(())
},
_ => self.items[self.focus].handle(event)
}
} else {
match event {
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
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)?;
true
},
_ => {}
_ => {
false
}
},
_ => {}
}
Ok(())
}
_ => false
})
}
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
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, .. })) => {
self.focused = true;
self.items[self.focus].handle(&AppEvent::Blur)?;
Ok(())
},
_ => self.items[self.focus].handle(event)
}
} else {
match event {
fn handle (&mut self, event: &AppEvent) -> Usually<bool> {
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)?;
true
},
_ => {}
_ => false
},
_ => {}
}
Ok(())
}
_ => false
})
}
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let mut w = 0u16;

View file

@ -112,17 +112,17 @@ pub use crate::{key, keymap};
pub fn handle_keymap <T> (
commands: &[KeyBinding<T>], state: &mut T, event: &AppEvent
) -> Result<(), Box<dyn Error>> {
) -> Result<bool, Box<dyn Error>> {
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)
}