mirror of
https://github.com/danbulant/mangui
synced 2026-07-06 11:20:34 +00:00
working events
This commit is contained in:
parent
5d53e10a32
commit
c785b36442
5 changed files with 64 additions and 19 deletions
|
|
@ -6,6 +6,7 @@ pub use winit::event::{TouchPhase, MouseScrollDelta, DeviceId, ModifiersState, V
|
||||||
|
|
||||||
use crate::SharedNode;
|
use crate::SharedNode;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct NodeEvent {
|
pub struct NodeEvent {
|
||||||
/// Target node of event.
|
/// Target node of event.
|
||||||
pub target: SharedNode,
|
pub target: SharedNode,
|
||||||
|
|
@ -16,6 +17,7 @@ pub struct NodeEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Different event types that can be sent to a node.
|
/// Different event types that can be sent to a node.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum InnerEvent {
|
pub enum InnerEvent {
|
||||||
Wheel {
|
Wheel {
|
||||||
phase: TouchPhase,
|
phase: TouchPhase,
|
||||||
|
|
@ -56,6 +58,7 @@ pub enum InnerEvent {
|
||||||
KeyUp(KeyboardEvent),
|
KeyUp(KeyboardEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct KeyboardEvent {
|
pub struct KeyboardEvent {
|
||||||
/// Logical location ("it's effect") of the key
|
/// Logical location ("it's effect") of the key
|
||||||
pub key: Option<VirtualKeyCode>,
|
pub key: Option<VirtualKeyCode>,
|
||||||
|
|
@ -77,6 +80,7 @@ pub struct KeyboardEvent {
|
||||||
pub device: DeviceId
|
pub device: DeviceId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct MouseEvent {
|
pub struct MouseEvent {
|
||||||
/// The button which fired the event (if any)
|
/// The button which fired the event (if any)
|
||||||
pub button: Option<MouseButton>,
|
pub button: Option<MouseButton>,
|
||||||
|
|
@ -214,14 +218,14 @@ impl MouseEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Copy, Clone, Default, Debug, PartialEq)]
|
||||||
pub(crate) struct MouseValue {
|
pub(crate) struct MouseValue {
|
||||||
pub last_location: Location,
|
pub last_location: Location,
|
||||||
pub buttons: u8
|
pub buttons: u8
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseValue {
|
impl MouseValue {
|
||||||
fn update_buttons(&mut self, button: MouseButton, state: ElementState) {
|
pub(crate) fn update_buttons(&mut self, button: MouseButton, state: ElementState) {
|
||||||
let buttons = MouseEvent::button_to_buttons(button);
|
let buttons = MouseEvent::button_to_buttons(button);
|
||||||
match state {
|
match state {
|
||||||
ElementState::Pressed => self.buttons |= buttons,
|
ElementState::Pressed => self.buttons |= buttons,
|
||||||
|
|
|
||||||
|
|
@ -81,15 +81,14 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
WindowEvent::MouseWheel { device_id, delta, phase, .. } => {},
|
WindowEvent::MouseWheel { device_id, delta, phase, .. } => {},
|
||||||
WindowEvent::CursorMoved { device_id, position, .. } => {
|
WindowEvent::CursorMoved { device_id, position, .. } => {
|
||||||
let mouse_value = mouse_values.get(&device_id);
|
let mouse_value = mouse_values.get(&device_id);
|
||||||
let (movement, location, buttons) = match mouse_value {
|
let (movement, location, mouse_value) = match mouse_value {
|
||||||
Some(mouse_value) => {
|
Some(mouse_value) => {
|
||||||
let location = (position.x, position.y).into();
|
let location = (position.x, position.y).into();
|
||||||
let movement = location - mouse_value.last_location;
|
let movement = location - mouse_value.last_location;
|
||||||
mouse_values.insert(device_id, MouseValue {
|
(movement, location, MouseValue {
|
||||||
last_location: location,
|
last_location: location,
|
||||||
buttons: mouse_value.buttons
|
buttons: mouse_value.buttons
|
||||||
});
|
})
|
||||||
(movement, location, mouse_value.buttons)
|
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let location = (position.x, position.y).into();
|
let location = (position.x, position.y).into();
|
||||||
|
|
@ -98,10 +97,11 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
last_location: location,
|
last_location: location,
|
||||||
buttons: 0
|
buttons: 0
|
||||||
};
|
};
|
||||||
mouse_values.insert(device_id, value);
|
(movement, location, value)
|
||||||
(movement, location, Default::default())
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let buttons = mouse_value.buttons;
|
||||||
|
mouse_values.insert(device_id, mouse_value);
|
||||||
|
|
||||||
let path = get_element_at(&root, &context, location);
|
let path = get_element_at(&root, &context, location);
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
Some(target_layout) => target_layout,
|
Some(target_layout) => target_layout,
|
||||||
None => { return; }
|
None => { return; }
|
||||||
};
|
};
|
||||||
let target_layout = taffy.layout(target_layout.to_owned()).unwrap();
|
let target_layout = context.taffy.layout(target_layout.to_owned()).unwrap();
|
||||||
let event = NodeEvent {
|
let event = NodeEvent {
|
||||||
target: path.last().unwrap().clone(),
|
target: path.last().unwrap().clone(),
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
|
|
@ -125,6 +125,10 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
offset: location - target_layout.location.into()
|
offset: location - target_layout.location.into()
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for node in path.iter().rev() {
|
||||||
|
node.write().unwrap().on_event(&event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
WindowEvent::DroppedFile(path) => {},
|
WindowEvent::DroppedFile(path) => {},
|
||||||
|
|
@ -143,7 +147,7 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
path: strong_focus_path.clone(),
|
path: strong_focus_path.clone(),
|
||||||
event: if focused { events::InnerEvent::Focus } else { events::InnerEvent::Blur }
|
event: if focused { events::InnerEvent::Focus } else { events::InnerEvent::Blur }
|
||||||
};
|
};
|
||||||
strong_focus_path.last().unwrap().write().unwrap().on_event(&focus_event.event);
|
strong_focus_path.last().unwrap().write().unwrap().on_event(&focus_event);
|
||||||
|
|
||||||
let focus_event = NodeEvent {
|
let focus_event = NodeEvent {
|
||||||
target: strong_focus_path.last().unwrap().clone(),
|
target: strong_focus_path.last().unwrap().clone(),
|
||||||
|
|
@ -152,7 +156,7 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
};
|
};
|
||||||
|
|
||||||
for node in strong_focus_path.iter().rev() {
|
for node in strong_focus_path.iter().rev() {
|
||||||
node.write().unwrap().on_event(&focus_event.event);
|
node.write().unwrap().on_event(&focus_event);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {}
|
None => {}
|
||||||
|
|
@ -162,10 +166,41 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
||||||
WindowEvent::KeyboardInput { device_id, input, is_synthetic } => {},
|
WindowEvent::KeyboardInput { device_id, input, is_synthetic } => {},
|
||||||
WindowEvent::MouseInput { device_id, state, button, .. } => {
|
WindowEvent::MouseInput { device_id, state, button, .. } => {
|
||||||
let mouse_value = mouse_values.get(&device_id);
|
let mouse_value = mouse_values.get(&device_id);
|
||||||
let mouse_value = match mouse_value {
|
let mut mouse_value = match mouse_value {
|
||||||
Some(mouse_value) => mouse_value,
|
Some(mouse_value) => mouse_value.clone(),
|
||||||
None => { return; } // Mouse move should be fired first
|
None => { return; } // Mouse move should be fired first
|
||||||
};
|
};
|
||||||
|
mouse_value.update_buttons(button, state);
|
||||||
|
|
||||||
|
let location = mouse_value.last_location;
|
||||||
|
let path = get_element_at(&root, &context, location);
|
||||||
|
|
||||||
|
match path {
|
||||||
|
Some(path) => {
|
||||||
|
let mevent = MouseEvent {
|
||||||
|
button: Some(button),
|
||||||
|
buttons: mouse_value.buttons,
|
||||||
|
client: location,
|
||||||
|
movement: Location::new(0., 0.),
|
||||||
|
device: device_id,
|
||||||
|
modifiers,
|
||||||
|
offset: Location::new(0., 0.)
|
||||||
|
};
|
||||||
|
let event = NodeEvent {
|
||||||
|
target: path.last().unwrap().clone(),
|
||||||
|
path: path.clone(),
|
||||||
|
event: match state {
|
||||||
|
winit::event::ElementState::Pressed => events::InnerEvent::MouseDown(mevent),
|
||||||
|
winit::event::ElementState::Released => events::InnerEvent::MouseUp(mevent)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for node in path.iter().rev() {
|
||||||
|
node.write().unwrap().on_event(&event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||||
WindowEvent::Resized(size) => {
|
WindowEvent::Resized(size) => {
|
||||||
|
|
|
||||||
|
|
@ -38,4 +38,6 @@ impl Node for Layout {
|
||||||
self.style.layout.size.width = Dimension::Points(width);
|
self.style.layout.size.width = Dimension::Points(width);
|
||||||
self.style.layout.size.height = Dimension::Points(height);
|
self.style.layout.size.height = Dimension::Points(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_event(&mut self, event: &crate::events::NodeEvent) {}
|
||||||
}
|
}
|
||||||
|
|
@ -64,19 +64,21 @@ pub trait Node: Debug {
|
||||||
/// Render the node, called after rendering it's children
|
/// Render the node, called after rendering it's children
|
||||||
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
|
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
|
||||||
fn render_post_children(&self, _context: &mut RenderContext, _layout: Layout) {}
|
fn render_post_children(&self, _context: &mut RenderContext, _layout: Layout) {}
|
||||||
|
/// Called when an event happens on the node. This is called after the children have been called.
|
||||||
|
/// Beware! Events include a path and target with [Arc<RwLock<Node>>]s, but you already have a write lock for this node!
|
||||||
|
/// Remember to check if the node is the same as self, and if it is, use self instead of the node in the path to prevent deadlocks!
|
||||||
|
fn on_event(&mut self, _event: &crate::events::NodeEvent) {}
|
||||||
|
|
||||||
|
|
||||||
/// Called when the size of window changes on the root node. Layouts do implement this.
|
/// Called when the size of window changes on the root node. Layouts do implement this.
|
||||||
/// Is an optional function instead of another trait because of missing support for trait upcasting
|
/// Is an optional function instead of another trait because of missing support for trait upcasting
|
||||||
// TODO: When rust supports trait upcasting, make this a trait
|
// TODO: When rust supports trait upcasting, make this a trait
|
||||||
fn resize(&mut self, _width: f32, _height: f32) {}
|
fn resize(&mut self, _width: f32, _height: f32) {}
|
||||||
|
|
||||||
/// Called when an event happens on the node. This is called after the children have been called.
|
|
||||||
/// Beware! Events include a path and target with [Arc<RwLock<Node>>]s, but you already have a write lock for this node!
|
|
||||||
/// Remember to check if the node is the same as self, and if it is, use self instead of the node in the path to prevent deadlocks!
|
|
||||||
fn on_event(&mut self, _event: &crate::events::InnerEvent) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_element_at(node: &SharedTNode, context: &RenderContext, location: Location) -> Option<Vec<SharedTNode>> {
|
pub fn get_element_at(node: &SharedTNode, context: &RenderContext, location: Location) -> Option<Vec<SharedTNode>> {
|
||||||
let children = node.read().unwrap().children();
|
let node_borrowed = node.read().unwrap();
|
||||||
|
let children = node_borrowed.children();
|
||||||
let taffy_node = context.node_layout.get(node);
|
let taffy_node = context.node_layout.get(node);
|
||||||
let taffy_node = match taffy_node {
|
let taffy_node = match taffy_node {
|
||||||
Some(taffy_node) => taffy_node,
|
Some(taffy_node) => taffy_node,
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,6 @@ impl Node for Rectangle {
|
||||||
&self.fill
|
&self.fill
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_event(&mut self, event: &crate::events::NodeEvent) {}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue