use crate::{script::ScriptEngine, tui::graph_api::RenderCmd};
use super::{EventType, HitMap, HitRegion};
#[derive(Debug, Default)]
pub struct HoverState {
current: Option<HitRegion>,
}
impl HoverState {
pub fn new() -> Self {
Self::default()
}
pub fn current(&self) -> Option<&HitRegion> {
self.current.as_ref()
}
}
pub fn on_move(
state: &mut HoverState,
hit_map: &HitMap,
engine: &mut ScriptEngine,
x: u32,
y: u32,
) -> Vec<RenderCmd> {
let mut cmds = Vec::new();
let new_hover = hit_map.hit_test(x, y);
let hover_changed = new_hover.map(|r| r.node_id) != state.current.as_ref().map(|r| r.node_id);
if !hover_changed {
return cmds;
}
if let Some(old) = state.current.take() {
cmds.extend(engine.fire_target(&old, EventType::MouseLeave, x, y));
cmds.extend(engine.fire(&old, EventType::MouseOut, x, y));
}
state.current = new_hover.cloned();
if let Some(region) = new_hover {
cmds.extend(engine.fire_target(region, EventType::MouseEnter, x, y));
cmds.extend(engine.fire(region, EventType::MouseOver, x, y));
}
cmds.push(RenderCmd::Hover {
node_id: new_hover.map(|r| r.node_id),
});
cmds
}
pub fn on_mouse_down(
hit_map: &HitMap,
engine: &mut ScriptEngine,
x: u32,
y: u32,
) -> Vec<RenderCmd> {
let Some(region) = hit_map.hit_test(x, y) else {
return Vec::new();
};
engine.fire(region, EventType::MouseDown, x, y)
}
pub fn on_mouse_up(hit_map: &HitMap, engine: &mut ScriptEngine, x: u32, y: u32) -> Vec<RenderCmd> {
let Some(region) = hit_map.hit_test(x, y) else {
return Vec::new();
};
engine.fire(region, EventType::MouseUp, x, y)
}
pub fn on_mouse_move_dispatch(
hit_map: &HitMap,
engine: &mut ScriptEngine,
x: u32,
y: u32,
) -> Vec<RenderCmd> {
let Some(region) = hit_map.hit_test(x, y) else {
return Vec::new();
};
engine.fire(region, EventType::MouseMove, x, y)
}
pub fn on_click(
state: &mut HoverState,
hit_map: &HitMap,
engine: &mut ScriptEngine,
x: u32,
y: u32,
) -> Vec<RenderCmd> {
let mut cmds = Vec::new();
let Some(region) = hit_map.hit_test(x, y) else {
return cmds;
};
if state.current.as_ref().map(|r| r.node_id) != Some(region.node_id) {
state.current = Some(region.clone());
cmds.push(RenderCmd::Hover {
node_id: Some(region.node_id),
});
}
cmds.extend(engine.fire(region, EventType::Click, x, y));
cmds
}