mirror of
https://github.com/danbulant/mangui
synced 2026-06-19 06:11:21 +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;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NodeEvent {
|
||||
/// Target node of event.
|
||||
pub target: SharedNode,
|
||||
|
|
@ -16,6 +17,7 @@ pub struct NodeEvent {
|
|||
}
|
||||
|
||||
/// Different event types that can be sent to a node.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum InnerEvent {
|
||||
Wheel {
|
||||
phase: TouchPhase,
|
||||
|
|
@ -56,6 +58,7 @@ pub enum InnerEvent {
|
|||
KeyUp(KeyboardEvent),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct KeyboardEvent {
|
||||
/// Logical location ("it's effect") of the key
|
||||
pub key: Option<VirtualKeyCode>,
|
||||
|
|
@ -77,6 +80,7 @@ pub struct KeyboardEvent {
|
|||
pub device: DeviceId
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MouseEvent {
|
||||
/// The button which fired the event (if any)
|
||||
pub button: Option<MouseButton>,
|
||||
|
|
@ -214,14 +218,14 @@ impl MouseEvent {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq)]
|
||||
pub(crate) struct MouseValue {
|
||||
pub last_location: Location,
|
||||
pub buttons: u8
|
||||
}
|
||||
|
||||
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);
|
||||
match state {
|
||||
ElementState::Pressed => self.buttons |= buttons,
|
||||
|
|
|
|||
|
|
@ -81,15 +81,14 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
|||
WindowEvent::MouseWheel { device_id, delta, phase, .. } => {},
|
||||
WindowEvent::CursorMoved { device_id, position, .. } => {
|
||||
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) => {
|
||||
let location = (position.x, position.y).into();
|
||||
let movement = location - mouse_value.last_location;
|
||||
mouse_values.insert(device_id, MouseValue {
|
||||
(movement, location, MouseValue {
|
||||
last_location: location,
|
||||
buttons: mouse_value.buttons
|
||||
});
|
||||
(movement, location, mouse_value.buttons)
|
||||
})
|
||||
},
|
||||
None => {
|
||||
let location = (position.x, position.y).into();
|
||||
|
|
@ -98,10 +97,11 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
|||
last_location: location,
|
||||
buttons: 0
|
||||
};
|
||||
mouse_values.insert(device_id, value);
|
||||
(movement, location, Default::default())
|
||||
(movement, location, value)
|
||||
}
|
||||
};
|
||||
let buttons = mouse_value.buttons;
|
||||
mouse_values.insert(device_id, mouse_value);
|
||||
|
||||
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,
|
||||
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 {
|
||||
target: path.last().unwrap().clone(),
|
||||
path: path.clone(),
|
||||
|
|
@ -125,6 +125,10 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
|||
offset: location - target_layout.location.into()
|
||||
})
|
||||
};
|
||||
|
||||
for node in path.iter().rev() {
|
||||
node.write().unwrap().on_event(&event);
|
||||
}
|
||||
}
|
||||
},
|
||||
WindowEvent::DroppedFile(path) => {},
|
||||
|
|
@ -143,7 +147,7 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
|||
path: strong_focus_path.clone(),
|
||||
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 {
|
||||
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() {
|
||||
node.write().unwrap().on_event(&focus_event.event);
|
||||
node.write().unwrap().on_event(&focus_event);
|
||||
}
|
||||
},
|
||||
None => {}
|
||||
|
|
@ -162,10 +166,41 @@ pub fn run_event_loop(root_node: SharedNode) -> ! {
|
|||
WindowEvent::KeyboardInput { device_id, input, is_synthetic } => {},
|
||||
WindowEvent::MouseInput { device_id, state, button, .. } => {
|
||||
let mouse_value = mouse_values.get(&device_id);
|
||||
let mouse_value = match mouse_value {
|
||||
Some(mouse_value) => mouse_value,
|
||||
let mut mouse_value = match mouse_value {
|
||||
Some(mouse_value) => mouse_value.clone(),
|
||||
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::Resized(size) => {
|
||||
|
|
|
|||
|
|
@ -38,4 +38,6 @@ impl Node for Layout {
|
|||
self.style.layout.size.width = Dimension::Points(width);
|
||||
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
|
||||
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
|
||||
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.
|
||||
/// 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
|
||||
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>> {
|
||||
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 = match taffy_node {
|
||||
Some(taffy_node) => taffy_node,
|
||||
|
|
|
|||
|
|
@ -40,4 +40,6 @@ impl Node for Rectangle {
|
|||
&self.fill
|
||||
);
|
||||
}
|
||||
|
||||
fn on_event(&mut self, event: &crate::events::NodeEvent) {}
|
||||
}
|
||||
Loading…
Reference in a new issue