Skip to content

Instantly share code, notes, and snippets.

@tuzz
Created April 19, 2020 10:04
Show Gist options
  • Save tuzz/b44c0603e740a3bb62707c9449295cc1 to your computer and use it in GitHub Desktop.
Save tuzz/b44c0603e740a3bb62707c9449295cc1 to your computer and use it in GitHub Desktop.
A convenience wrapper for handling events in Rust using web_sys
// The EventHandler::new method takes three arguments:
//
// 1) The Rust function to call to handle the event
// 2) The registration function
// 3) The deregistration function
//
// The deregistration function is called when the EventHandler is dropped.
// This is similar to React's useEffect cleanup pattern.
pub struct EventHandler {
closure: Closure<dyn Fn(JsValue)>,
deregister: Box<dyn Fn(&Function)>,
}
impl EventHandler {
#[must_use = "the handler must be owned, otherwise it will be immediately deregistered"]
pub fn new<H: Fn(JsValue) + 'static, R: Fn(&Function), D: Fn(&Function) + 'static>(handler: H, register: R, deregister: D) -> Self {
let boxed = Box::new(handler) as Box<dyn Fn(_)>;
let closure = Closure::wrap(boxed);
let js_func = closure.as_ref().unchecked_ref();
register(js_func);
Self { closure, deregister: Box::new(deregister) }
}
}
impl Drop for EventHandler {
fn drop(&mut self) {
let js_func = self.closure.as_ref().unchecked_ref();
(self.deregister)(js_func);
}
}
pub struct KeyboardInput {
event_handler: EventHandler,
}
impl KeyboardInput {
pub fn new() -> Self {
let event_handler = EventHandler::new(Self::handle_click, |h| {
web_sys::window().unwrap()
.add_event_listener_with_callback("keydown", h).unwrap();
}, |h| {
web_sys::window().unwrap()
.remove_event_listener_with_callback("keydown", h).unwrap();
});
Self { event_handler }
}
fn handle_click<E: Into<KeyboardEvent>>(event: E) {
let event = event.into();
let key = event.key_code();
log!("pressed {}", key);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment