keyboard progress & refactors
This commit is contained in:
@@ -7,26 +7,44 @@ use crate::{
|
||||
widget::{WidgetData, WidgetObj},
|
||||
};
|
||||
|
||||
// TODO: mouse index
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
}
|
||||
|
||||
pub struct MouseDownEvent {
|
||||
pub pos: Vec2,
|
||||
pub button: MouseButton,
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseLeaveEvent {
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseMotionEvent {
|
||||
pub pos: Vec2,
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseUpEvent {
|
||||
pub pos: Vec2,
|
||||
pub button: MouseButton,
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseWheelEvent {
|
||||
pub pos: Vec2,
|
||||
pub shift: Vec2,
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
InternalStateChange,
|
||||
MouseDown(MouseDownEvent),
|
||||
MouseLeave(MouseLeaveEvent),
|
||||
MouseMotion(MouseMotionEvent),
|
||||
MouseUp(MouseUpEvent),
|
||||
MouseWheel(MouseWheelEvent),
|
||||
@@ -46,6 +64,7 @@ impl Event {
|
||||
Event::MouseMotion(evt) => self.test_transform_pos(transform, &evt.pos),
|
||||
Event::MouseUp(evt) => self.test_transform_pos(transform, &evt.pos),
|
||||
Event::MouseWheel(evt) => self.test_transform_pos(transform, &evt.pos),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,10 +118,14 @@ impl<'a> WidgetCallback<'a> for CallbackData<'a> {
|
||||
|
||||
pub type MouseEnterCallback = Box<dyn Fn(&mut CallbackData)>;
|
||||
pub type MouseLeaveCallback = Box<dyn Fn(&mut CallbackData)>;
|
||||
pub type MouseClickCallback = Box<dyn Fn(&mut CallbackData)>;
|
||||
pub type MousePressCallback = Box<dyn Fn(&mut CallbackData, MouseButton)>;
|
||||
pub type MouseReleaseCallback = Box<dyn Fn(&mut CallbackData, MouseButton)>;
|
||||
pub type InternalStateChangeCallback = Box<dyn Fn(&mut CallbackData)>;
|
||||
|
||||
pub enum EventListener {
|
||||
MouseEnter(MouseEnterCallback),
|
||||
MouseLeave(MouseLeaveCallback),
|
||||
MouseClick(MouseClickCallback),
|
||||
MousePress(MousePressCallback),
|
||||
MouseRelease(MouseReleaseCallback),
|
||||
InternalStateChange(InternalStateChangeCallback),
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ impl ParserResult {
|
||||
}
|
||||
|
||||
pub fn process_template(
|
||||
&self,
|
||||
&mut self,
|
||||
template_name: &str,
|
||||
layout: &mut Layout,
|
||||
widget_id: WidgetID,
|
||||
@@ -90,6 +90,10 @@ impl ParserResult {
|
||||
widget_id,
|
||||
)?;
|
||||
|
||||
ctx.ids.into_iter().for_each(|(id, key)| {
|
||||
self.ids.insert(id, key);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,56 @@ pub mod text;
|
||||
pub mod util;
|
||||
|
||||
pub struct WidgetData {
|
||||
pub hovered: bool,
|
||||
pub pressed: bool,
|
||||
hovered: usize,
|
||||
pressed: usize,
|
||||
pub scrolling: Vec2, // normalized, 0.0-1.0. Not used in case if overflow != scroll
|
||||
pub transform: glam::Mat4,
|
||||
}
|
||||
|
||||
impl WidgetData {
|
||||
pub fn set_device_pressed(&mut self, device: usize, pressed: bool) -> bool {
|
||||
let bit = 1 << device;
|
||||
let state_changed;
|
||||
if pressed {
|
||||
state_changed = self.pressed == 0;
|
||||
self.pressed |= bit;
|
||||
} else {
|
||||
state_changed = self.pressed == bit;
|
||||
self.pressed &= !bit;
|
||||
}
|
||||
state_changed
|
||||
}
|
||||
|
||||
pub fn set_device_hovered(&mut self, device: usize, hovered: bool) -> bool {
|
||||
let bit = 1 << device;
|
||||
let state_changed;
|
||||
if hovered {
|
||||
state_changed = self.hovered == 0;
|
||||
self.hovered |= bit;
|
||||
} else {
|
||||
state_changed = self.hovered == bit;
|
||||
self.hovered &= !bit;
|
||||
}
|
||||
state_changed
|
||||
}
|
||||
|
||||
pub fn get_pressed(&self, device: usize) -> bool {
|
||||
self.pressed & (1 << device) != 0
|
||||
}
|
||||
|
||||
pub fn get_hovered(&self, device: usize) -> bool {
|
||||
self.hovered & (1 << device) != 0
|
||||
}
|
||||
|
||||
pub fn is_pressed(&self) -> bool {
|
||||
self.pressed != 0
|
||||
}
|
||||
|
||||
pub fn is_hovered(&self) -> bool {
|
||||
self.hovered != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WidgetState {
|
||||
pub data: WidgetData,
|
||||
pub obj: Box<dyn WidgetObj>,
|
||||
@@ -32,8 +77,8 @@ impl WidgetState {
|
||||
fn new(obj: Box<dyn WidgetObj>) -> anyhow::Result<WidgetState> {
|
||||
Ok(Self {
|
||||
data: WidgetData {
|
||||
hovered: false,
|
||||
pressed: false,
|
||||
hovered: 0,
|
||||
pressed: 0,
|
||||
scrolling: Vec2::default(),
|
||||
transform: glam::Mat4::IDENTITY,
|
||||
},
|
||||
@@ -252,32 +297,40 @@ impl WidgetState {
|
||||
) -> EventResult {
|
||||
let hovered = event.test_mouse_within_transform(params.transform_stack.get());
|
||||
|
||||
let mut just_clicked = false;
|
||||
let mut pressed_changed_button = None;
|
||||
let mut hovered_changed = false;
|
||||
|
||||
match &event {
|
||||
Event::MouseDown(_) => {
|
||||
if self.data.hovered {
|
||||
self.data.pressed = true;
|
||||
}
|
||||
Event::MouseDown(e) => {
|
||||
pressed_changed_button = self
|
||||
.data
|
||||
.set_device_pressed(e.device, true)
|
||||
.then_some(e.button);
|
||||
}
|
||||
Event::MouseUp(_) => {
|
||||
if self.data.pressed {
|
||||
self.data.pressed = false;
|
||||
just_clicked = self.data.hovered;
|
||||
}
|
||||
Event::MouseUp(e) => {
|
||||
pressed_changed_button = self
|
||||
.data
|
||||
.set_device_pressed(e.device, false)
|
||||
.then_some(e.button);
|
||||
}
|
||||
Event::MouseWheel(e) => {
|
||||
if self.process_wheel(params, e) {
|
||||
return EventResult::Consumed;
|
||||
}
|
||||
}
|
||||
Event::MouseMotion(e) => {
|
||||
hovered_changed |= self.data.set_device_hovered(e.device, hovered);
|
||||
}
|
||||
Event::MouseLeave(e) => {
|
||||
hovered_changed |= self.data.set_device_hovered(e.device, false);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// TODO: simplify this behemoth, I gave up arguing with the compiler
|
||||
for listener in &self.event_listeners {
|
||||
match listener {
|
||||
EventListener::MouseEnter(callback) => {
|
||||
if hovered && !self.data.hovered {
|
||||
if hovered_changed && self.data.is_hovered() {
|
||||
let mut data = CallbackData {
|
||||
obj: self.obj.as_mut(),
|
||||
widget_data: &mut self.data,
|
||||
@@ -295,7 +348,7 @@ impl WidgetState {
|
||||
}
|
||||
}
|
||||
EventListener::MouseLeave(callback) => {
|
||||
if !hovered && self.data.hovered {
|
||||
if hovered_changed && !self.data.is_hovered() {
|
||||
let mut data = CallbackData {
|
||||
obj: self.obj.as_mut(),
|
||||
widget_data: &mut self.data,
|
||||
@@ -312,8 +365,8 @@ impl WidgetState {
|
||||
}
|
||||
}
|
||||
}
|
||||
EventListener::MouseClick(callback) => {
|
||||
if just_clicked {
|
||||
EventListener::MousePress(callback) => {
|
||||
if let Some(button) = pressed_changed_button.filter(|_| self.data.is_pressed()) {
|
||||
let mut data = CallbackData {
|
||||
obj: self.obj.as_mut(),
|
||||
widget_data: &mut self.data,
|
||||
@@ -324,19 +377,49 @@ impl WidgetState {
|
||||
node_id,
|
||||
needs_redraw: false,
|
||||
};
|
||||
callback(&mut data);
|
||||
callback(&mut data, button);
|
||||
if data.needs_redraw {
|
||||
*params.needs_redraw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
EventListener::MouseRelease(callback) => {
|
||||
if let Some(button) = pressed_changed_button.filter(|_| !self.data.is_pressed()) {
|
||||
let mut data = CallbackData {
|
||||
obj: self.obj.as_mut(),
|
||||
widget_data: &mut self.data,
|
||||
widgets: params.widgets,
|
||||
animations: params.animations,
|
||||
dirty_nodes: params.dirty_nodes,
|
||||
widget_id,
|
||||
node_id,
|
||||
needs_redraw: false,
|
||||
};
|
||||
callback(&mut data, button);
|
||||
if data.needs_redraw {
|
||||
*params.needs_redraw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
EventListener::InternalStateChange(callback) => {
|
||||
let mut data = CallbackData {
|
||||
obj: self.obj.as_mut(),
|
||||
widget_data: &mut self.data,
|
||||
widgets: params.widgets,
|
||||
animations: params.animations,
|
||||
dirty_nodes: params.dirty_nodes,
|
||||
widget_id,
|
||||
node_id,
|
||||
needs_redraw: false,
|
||||
};
|
||||
callback(&mut data);
|
||||
if data.needs_redraw {
|
||||
*params.needs_redraw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.data.hovered != hovered {
|
||||
self.data.hovered = hovered;
|
||||
}
|
||||
|
||||
EventResult::Pass
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user