Skip to content

Commit fac07dc

Browse files
synth
1 parent 8ec360d commit fac07dc

File tree

1 file changed

+141
-125
lines changed

1 file changed

+141
-125
lines changed

examples/synth/src/midi_keyboard.rs

Lines changed: 141 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -392,145 +392,161 @@ impl MidiKeyboard {
392392
/// # Arguments
393393
/// * `config` - Configuration for the MIDI keyboard
394394
pub fn show(config: MidiKeyboardConfig) -> impl View {
395-
state(
396-
move || MidiKeyboardState::new(config.clone()),
397-
|s, _| {
398-
canvas(move |cx, rect, vger| {
399-
// Pre-calculate commonly used values
400-
let total_white_keys = cx[s].num_white_keys();
401-
let white_key_width = rect.width() / total_white_keys as f32;
402-
let key_height = rect.height();
403-
let black_key_height = key_height * 0.6;
404-
405-
// Create paint indices once for reuse
406-
let white_paint = vger.color_paint(vger::Color::new(1.0, 1.0, 1.0, 1.0));
407-
let white_held_paint = vger.color_paint(vger::Color::new(0.8, 0.8, 0.8, 1.0));
408-
let white_hover_paint =
409-
vger.color_paint(vger::Color::new(0.85, 0.85, 0.85, 1.0));
410-
let black_paint = vger.color_paint(vger::Color::new(0.1, 0.1, 0.1, 1.0));
411-
let black_held_paint = vger.color_paint(vger::Color::new(0.3, 0.3, 0.3, 1.0));
412-
let black_hover_paint = vger.color_paint(vger::Color::new(0.2, 0.2, 0.2, 1.0));
413-
414-
// Calculate hovered key using binary search for mouse position
415-
let hovered_key_idx = if let Some(mouse_position) = cx[s].mouse_position {
416-
Self::find_hovered_key(
417-
&cx[s].keyboard_layout,
418-
mouse_position,
419-
white_key_width,
420-
key_height,
421-
black_key_height,
422-
)
423-
} else {
424-
None
425-
};
426-
427-
// Batch render white keys
428-
let white_keys: Vec<_> = cx[s]
429-
.keyboard_layout
430-
.iter()
431-
.enumerate()
432-
.filter(|(_, (_, _, is_black))| !is_black)
433-
.collect();
434-
435-
for (index, (x, width, _)) in white_keys {
436-
let key_x = x * white_key_width;
437-
let key_width = white_key_width * width;
438-
let is_held = cx[s].keys[index].is_some();
439-
let is_hovered = hovered_key_idx == Some(index as MidiNoteId);
440-
441-
let paint = if is_held {
442-
white_held_paint
443-
} else if is_hovered {
444-
white_hover_paint
395+
focus(move |has_focus| {
396+
let config = config.clone();
397+
state(
398+
move || MidiKeyboardState::new(config.clone()),
399+
move |s, _| {
400+
canvas(move |cx, rect, vger| {
401+
// Pre-calculate commonly used values
402+
let total_white_keys = cx[s].num_white_keys();
403+
let white_key_width = rect.width() / total_white_keys as f32;
404+
let key_height = rect.height();
405+
let black_key_height = key_height * 0.6;
406+
407+
// Create paint indices once for reuse
408+
let white_paint = vger.color_paint(vger::Color::new(1.0, 1.0, 1.0, 1.0));
409+
let white_held_paint =
410+
vger.color_paint(vger::Color::new(0.8, 0.8, 0.8, 1.0));
411+
let white_hover_paint =
412+
vger.color_paint(vger::Color::new(0.85, 0.85, 0.85, 1.0));
413+
let black_paint = vger.color_paint(vger::Color::new(0.1, 0.1, 0.1, 1.0));
414+
let black_held_paint =
415+
vger.color_paint(vger::Color::new(0.3, 0.3, 0.3, 1.0));
416+
let black_hover_paint =
417+
vger.color_paint(vger::Color::new(0.2, 0.2, 0.2, 1.0));
418+
419+
// Calculate hovered key using binary search for mouse position
420+
let hovered_key_idx = if let Some(mouse_position) = cx[s].mouse_position {
421+
Self::find_hovered_key(
422+
&cx[s].keyboard_layout,
423+
mouse_position,
424+
white_key_width,
425+
key_height,
426+
black_key_height,
427+
)
445428
} else {
446-
white_paint
429+
None
447430
};
448431

449-
let rect = LocalRect::new(
450-
LocalPoint::new(key_x, 0.0),
451-
LocalSize::new(key_width, key_height),
452-
);
453-
vger.fill_rect(rect, 0.0, paint);
454-
}
455-
456-
// Batch render black keys
457-
let black_keys: Vec<_> = cx[s]
458-
.keyboard_layout
459-
.iter()
460-
.enumerate()
461-
.filter(|(_, (_, _, is_black))| *is_black)
462-
.collect();
463-
464-
for (index, (x, width, _)) in black_keys {
465-
let key_x = x * white_key_width;
466-
let key_width = white_key_width * width;
467-
let is_held = cx[s].keys[index].is_some();
468-
let is_hovered = hovered_key_idx == Some(index as MidiNoteId);
469-
470-
let paint = if is_held {
471-
black_held_paint
472-
} else if is_hovered {
473-
black_hover_paint
474-
} else {
475-
black_paint
476-
};
477-
478-
let rect = LocalRect::new(
479-
LocalPoint::new(key_x, key_height - black_key_height),
480-
LocalSize::new(key_width, black_key_height),
481-
);
482-
vger.fill_rect(rect, 0.1 * key_width, paint);
483-
}
432+
// Batch render white keys
433+
let white_keys: Vec<_> = cx[s]
434+
.keyboard_layout
435+
.iter()
436+
.enumerate()
437+
.filter(|(_, (_, _, is_black))| !is_black)
438+
.collect();
439+
440+
for (index, (x, width, _)) in white_keys {
441+
let key_x = x * white_key_width;
442+
let key_width = white_key_width * width;
443+
let is_held = cx[s].keys[index].is_some();
444+
let is_hovered = hovered_key_idx == Some(index as MidiNoteId);
445+
446+
let paint = if is_held {
447+
white_held_paint
448+
} else if is_hovered {
449+
white_hover_paint
450+
} else {
451+
white_paint
452+
};
453+
454+
let rect = LocalRect::new(
455+
LocalPoint::new(key_x, 0.0),
456+
LocalSize::new(key_width, key_height),
457+
);
458+
vger.fill_rect(rect, 0.0, paint);
459+
}
484460

485-
cx[s].hovered_key = hovered_key_idx;
486-
})
487-
.drag_p(
488-
move |cx, local_position, gesture_state, mouse_button| match gesture_state {
489-
GestureState::Began => {
490-
if mouse_button == Some(MouseButton::Left) {
491-
cx[s].mouse_dragging = true;
492-
cx[s].current_drag_key = cx[s].hovered_key;
493-
if let Some(current_drag_key) = cx[s].current_drag_key {
494-
let default_velocity = cx[s].config.default_velocity;
495-
let _ = cx[s].press_key(current_drag_key, default_velocity);
496-
}
497-
}
461+
// Batch render black keys
462+
let black_keys: Vec<_> = cx[s]
463+
.keyboard_layout
464+
.iter()
465+
.enumerate()
466+
.filter(|(_, (_, _, is_black))| *is_black)
467+
.collect();
468+
469+
for (index, (x, width, _)) in black_keys {
470+
let key_x = x * white_key_width;
471+
let key_width = white_key_width * width;
472+
let is_held = cx[s].keys[index].is_some();
473+
let is_hovered = hovered_key_idx == Some(index as MidiNoteId);
474+
475+
let paint = if is_held {
476+
black_held_paint
477+
} else if is_hovered {
478+
black_hover_paint
479+
} else {
480+
black_paint
481+
};
482+
483+
let rect = LocalRect::new(
484+
LocalPoint::new(key_x, key_height - black_key_height),
485+
LocalSize::new(key_width, black_key_height),
486+
);
487+
vger.fill_rect(rect, 0.1 * key_width, paint);
498488
}
499-
GestureState::Changed => {
500-
if cx[s].mouse_position.is_some() {
501-
cx[s].mouse_position = Some(local_position);
502-
if cx[s].current_drag_key != cx[s].hovered_key {
503-
if let Some(preview_drag_key) = cx[s].current_drag_key {
504-
let _ = cx[s].release_key(preview_drag_key);
505-
}
489+
490+
cx[s].hovered_key = hovered_key_idx;
491+
})
492+
// .key(move |cx, k| {
493+
// if has_focus {
494+
// println!("key pressed: {:#?}", k);
495+
// }
496+
// })
497+
// .key_released(move |cx, k| {
498+
// if has_focus {
499+
// println!("key released: {:#?}", k);
500+
// }
501+
// })
502+
.drag_p(move |cx, local_position, gesture_state, mouse_button| {
503+
match gesture_state {
504+
GestureState::Began => {
505+
if mouse_button == Some(MouseButton::Left) {
506+
cx[s].mouse_dragging = true;
506507
cx[s].current_drag_key = cx[s].hovered_key;
507508
if let Some(current_drag_key) = cx[s].current_drag_key {
508509
let default_velocity = cx[s].config.default_velocity;
509510
let _ = cx[s].press_key(current_drag_key, default_velocity);
510511
}
511512
}
512513
}
514+
GestureState::Changed => {
515+
if cx[s].mouse_position.is_some() {
516+
cx[s].mouse_position = Some(local_position);
517+
if cx[s].current_drag_key != cx[s].hovered_key {
518+
if let Some(preview_drag_key) = cx[s].current_drag_key {
519+
let _ = cx[s].release_key(preview_drag_key);
520+
}
521+
cx[s].current_drag_key = cx[s].hovered_key;
522+
if let Some(current_drag_key) = cx[s].current_drag_key {
523+
let default_velocity = cx[s].config.default_velocity;
524+
let _ =
525+
cx[s].press_key(current_drag_key, default_velocity);
526+
}
527+
}
528+
}
529+
}
530+
GestureState::Ended => {
531+
cx[s].mouse_dragging = false;
532+
cx[s].current_drag_key = None;
533+
cx[s].release_not_pressed_keys();
534+
}
535+
#[allow(unreachable_patterns)]
536+
_ => (),
513537
}
514-
GestureState::Ended => {
515-
cx[s].mouse_dragging = false;
516-
cx[s].current_drag_key = None;
517-
cx[s].release_not_pressed_keys();
538+
})
539+
.hover_p(move |cx, hover_position| {
540+
cx[s].mouse_position = Some(hover_position);
541+
})
542+
.hover(move |cx, is_hovering| {
543+
if !is_hovering {
544+
cx[s].mouse_position = None;
518545
}
519-
#[allow(unreachable_patterns)]
520-
_ => (),
521-
},
522-
)
523-
.hover_p(move |cx, hover_position| {
524-
cx[s].mouse_position = Some(hover_position);
525-
})
526-
.hover(move |cx, is_hovering| {
527-
if !is_hovering {
528-
cx[s].mouse_position = None;
529-
println!("stopped hovering");
530-
}
531-
})
532-
},
533-
)
546+
})
547+
},
548+
)
549+
})
534550
}
535551

536552
fn find_hovered_key(

0 commit comments

Comments
 (0)