From e04b1b14ad703f8b2eefad4ba2f25fda8833c674 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Wed, 18 Oct 2023 08:51:11 -0700 Subject: [PATCH] Added keyboard_input --- src/context.rs | 13 ++++++++++++- src/widget.rs | 13 ++++++++++++- src/widgets/button.rs | 39 ++++++++++++++++++++++++++++++++++----- src/window.rs | 20 +++++++++++++++----- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/src/context.rs b/src/context.rs index 7f7930f..68ac880 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,6 @@ use std::ops::{Deref, DerefMut}; -use kludgine::app::winit::event::{DeviceId, MouseButton}; +use kludgine::app::winit::event::{DeviceId, KeyEvent, MouseButton}; use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{IntoSigned, Point, Rect, Size}; @@ -108,6 +108,17 @@ impl<'context, 'window> Context<'context, 'window> { .mouse_up(location, device_id, button, self); } + pub fn keyboard_input( + &mut self, + device_id: DeviceId, + input: KeyEvent, + is_synthetic: bool, + ) -> EventHandling { + self.current_node + .lock() + .keyboard_input(device_id, input, is_synthetic, self) + } + #[must_use] pub fn push_child(&self, child: BoxedWidget) -> ManagedWidget { self.current_node diff --git a/src/widget.rs b/src/widget.rs index e1efc3b..b1cf0ef 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -5,7 +5,7 @@ use std::panic::UnwindSafe; use std::sync::{Arc, Mutex, MutexGuard, PoisonError}; use kludgine::app::winit::error::EventLoopError; -use kludgine::app::winit::event::{DeviceId, MouseButton}; +use kludgine::app::winit::event::{DeviceId, KeyEvent, MouseButton}; use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{Point, Size}; @@ -85,6 +85,17 @@ pub trait Widget: Send + UnwindSafe + Debug + 'static { context: &mut Context<'_, '_>, ) { } + + #[allow(unused_variables)] + fn keyboard_input( + &mut self, + device_id: DeviceId, + input: KeyEvent, + is_synthetic: bool, + context: &mut Context<'_, '_>, + ) -> EventHandling { + UNHANDLED + } } pub type EventHandling = ControlFlow; diff --git a/src/widgets/button.rs b/src/widgets/button.rs index aefc478..084f7a2 100644 --- a/src/widgets/button.rs +++ b/src/widgets/button.rs @@ -1,6 +1,7 @@ use std::panic::UnwindSafe; -use kludgine::app::winit::event::{DeviceId, MouseButton}; +use kludgine::app::winit::event::{DeviceId, ElementState, KeyEvent, MouseButton}; +use kludgine::app::winit::keyboard::KeyCode; use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{Point, Rect, Size}; use kludgine::shapes::{Shape, StrokeOptions}; @@ -8,7 +9,7 @@ use kludgine::Color; use crate::context::Context; use crate::graphics::Graphics; -use crate::widget::{Callback, EventHandling, IntoValue, Value, Widget, HANDLED}; +use crate::widget::{Callback, EventHandling, IntoValue, Value, Widget, HANDLED, UNHANDLED}; #[derive(Debug)] pub struct Button { @@ -34,6 +35,12 @@ impl Button { self.on_click = Some(Callback::new(callback)); self } + + fn invoke_on_click(&mut self) { + if let Some(on_click) = self.on_click.as_mut() { + on_click.invoke(()); + } + } } impl Widget for Button { @@ -138,9 +145,7 @@ impl Widget for Button { { context.focus(); - if let Some(on_click) = self.on_click.as_mut() { - on_click.invoke(()); - } + self.invoke_on_click(); } } } @@ -162,6 +167,30 @@ impl Widget for Button { }) } + fn keyboard_input( + &mut self, + _device_id: DeviceId, + input: KeyEvent, + _is_synthetic: bool, + context: &mut Context<'_, '_>, + ) -> EventHandling { + if input.physical_key == KeyCode::Space { + let changed = match input.state { + ElementState::Pressed => context.activate(), + ElementState::Released => { + self.invoke_on_click(); + context.deactivate() + } + }; + if changed { + context.set_needs_redraw(); + } + HANDLED + } else { + UNHANDLED + } + } + fn unhover(&mut self, context: &mut Context<'_, '_>) { context.set_needs_redraw(); } diff --git a/src/window.rs b/src/window.rs index 57fba10..2903850 100644 --- a/src/window.rs +++ b/src/window.rs @@ -4,7 +4,7 @@ use std::panic::{AssertUnwindSafe, UnwindSafe}; use kludgine::app::winit::dpi::PhysicalPosition; use kludgine::app::winit::error::EventLoopError; -use kludgine::app::winit::event::{DeviceId, ElementState, MouseButton}; +use kludgine::app::winit::event::{DeviceId, ElementState, KeyEvent, MouseButton}; use kludgine::app::winit::keyboard::KeyCode; use kludgine::app::WindowBehavior as _; use kludgine::figures::units::Px; @@ -197,11 +197,21 @@ where fn keyboard_input( &mut self, mut window: RunningWindow<'_>, - _device_id: DeviceId, - input: kludgine::app::winit::event::KeyEvent, - _is_synthetic: bool, + device_id: DeviceId, + input: KeyEvent, + is_synthetic: bool, ) { - if !input.state.is_pressed() { + let handled = if let Some(focus) = self.root.tree.focused_widget() { + let focus = self.root.tree.widget(focus); + let mut focus = Context::new(&focus, &mut window); + recursively_handle_event(&mut focus, |widget| { + widget.keyboard_input(device_id, input.clone(), is_synthetic) + }) + .is_some() + } else { + false + }; + if !handled && !input.state.is_pressed() { match input.physical_key { KeyCode::KeyW if window.modifiers().state().primary() => { if self.request_close(&mut window) {