use super::tree_paths::widget_at_path;
use crate::event::{Event, EventResult, Modifiers, MouseButton};
use crate::geometry::Point;
use crate::widget::tree::{active_modal_path, dispatch_event, hit_test_subtree};
use crate::widget::tree_inspector::set_current_mouse_world;
use crate::widget::{App, Widget};
impl App {
pub(crate) fn extend_modal_path(&self, modal_path: &[usize], pos_in_root: Point) -> Vec<usize> {
let mut widget: &dyn Widget = self.root.as_ref();
let mut pos = pos_in_root;
for &index in modal_path {
let Some(child) = widget.children().get(index) else {
return modal_path.to_vec();
};
let bounds = child.bounds();
pos = Point::new(pos.x - bounds.x, pos.y - bounds.y);
widget = child.as_ref();
}
let mut full = modal_path.to_vec();
if let Some(sub_path) = hit_test_subtree(widget, pos) {
full.extend(sub_path);
}
full
}
pub fn on_mouse_move(&mut self, screen_x: f64, screen_y: f64) {
crate::cursor::reset_cursor_icon();
let screen = self.flip_y(screen_x, screen_y);
if crate::widgets::on_screen_keyboard::handle_software_keyboard_mouse_move(screen) {
self.drain_keyboard_synthetic_keys();
return;
}
let pos = super::keyboard_scroll::lift_to_world(screen);
set_current_mouse_world(pos);
if let Some(path) = active_modal_path(self.root.as_ref()) {
let path = self.extend_modal_path(&path, pos);
let event = Event::MouseMove { pos };
dispatch_event(&mut self.root, &path, &event, pos);
self.hovered = Some(path);
return;
}
self.dispatch_mouse_move(pos);
}
pub fn on_mouse_down(
&mut self,
screen_x: f64,
screen_y: f64,
button: MouseButton,
mods: Modifiers,
) {
let screen = self.flip_y(screen_x, screen_y);
if crate::widgets::on_screen_keyboard::handle_software_keyboard_mouse_down(
screen, button, mods,
) {
return;
}
let pos = super::keyboard_scroll::lift_to_world(screen);
set_current_mouse_world(pos);
let modal_path = active_modal_path(self.root.as_ref());
let event = Event::MouseDown {
pos,
button,
modifiers: mods,
};
if let Some(path) = modal_path {
let path = self.extend_modal_path(&path, pos);
if widget_at_path(&mut self.root, &path).is_focusable() {
self.set_focus(Some(path.clone()));
} else {
self.set_focus(None);
}
if dispatch_event(&mut self.root, &path, &event, pos) == EventResult::Consumed {
self.captured = Some(path);
}
return;
}
let hit = self.compute_hit(pos);
if let Some(ref path) = hit {
let w = widget_at_path(&mut self.root, path);
if w.is_focusable() {
self.set_focus(Some(path.clone()));
} else {
self.set_focus(None);
}
} else {
self.set_focus(None);
}
if let Some(mut path) = hit {
let result = dispatch_event(&mut self.root, &path, &event, pos);
if result == EventResult::Consumed {
self.maybe_bring_to_front(&mut path);
let capture_path = self.compute_hit(pos).unwrap_or(path);
self.captured = Some(capture_path);
}
}
}
pub fn on_mouse_up(
&mut self,
screen_x: f64,
screen_y: f64,
button: MouseButton,
mods: Modifiers,
) {
let screen = self.flip_y(screen_x, screen_y);
if crate::widgets::on_screen_keyboard::handle_software_keyboard_mouse_up(
screen, button, mods,
) {
self.captured = None;
self.drain_keyboard_synthetic_keys();
return;
}
let pos = super::keyboard_scroll::lift_to_world(screen);
set_current_mouse_world(pos);
let event = Event::MouseUp {
pos,
button,
modifiers: mods,
};
if let Some(path) = active_modal_path(self.root.as_ref()) {
let path = self
.captured
.take()
.unwrap_or_else(|| self.extend_modal_path(&path, pos));
dispatch_event(&mut self.root, &path, &event, pos);
return;
}
if let Some(path) = self.captured.take() {
dispatch_event(&mut self.root, &path, &event, pos);
} else {
let hit = self.compute_hit(pos);
if let Some(path) = hit {
dispatch_event(&mut self.root, &path, &event, pos);
}
}
}
}