use frus_widgets::{Point, Ui, WidgetId};
use crate::gesture::PointerKind;
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub(crate) struct Hover {
at: Option<Point>,
}
impl Hover {
pub(crate) fn event(&mut self, kind: PointerKind, position: Point, touch: bool) {
self.at = match (kind, touch) {
(PointerKind::Up | PointerKind::Cancel, true) => None,
_ => Some(position),
};
}
pub(crate) fn left(&mut self) {
self.at = None;
}
pub(crate) fn target<Msg: Clone>(&self, ui: &Ui<Msg>) -> Option<WidgetId> {
self.at.and_then(|point| ui.hit(point))
}
}
#[cfg(test)]
mod tests {
use super::*;
use frus_widgets::{build_ui, BackButton, Container, Flex, Runtime, Size, Theme};
const BUTTON: Point = Point::new(24.0, 24.0);
fn frame(offset: f32) -> Ui<()> {
let root = Flex::column()
.width(200.0)
.height(400.0)
.child(Container::new().height(offset))
.child(BackButton::new().on_press(()));
build_ui(
&root,
Size::new(200.0, 400.0),
&Runtime::default(),
&Theme::default(),
)
}
#[test]
fn a_finger_hovers_what_it_touches_from_the_moment_it_is_down() {
let ui = frame(0.0);
let mut hover = Hover::default();
hover.event(PointerKind::Down, BUTTON, true);
assert!(hover.target(&ui).is_some(), "the button under the finger");
}
#[test]
fn a_finger_that_has_lifted_hovers_nothing() {
let ui = frame(0.0);
for ending in [PointerKind::Up, PointerKind::Cancel] {
let mut hover = Hover::default();
hover.event(PointerKind::Down, BUTTON, true);
hover.event(ending, BUTTON, true);
assert_eq!(hover.target(&ui), None, "after {ending:?}");
}
}
#[test]
fn a_mouse_still_hovers_after_its_button_is_released() {
let ui = frame(0.0);
let mut hover = Hover::default();
hover.event(PointerKind::Down, BUTTON, false);
hover.event(PointerKind::Up, BUTTON, false);
assert!(hover.target(&ui).is_some());
hover.left();
assert_eq!(hover.target(&ui), None, "until it leaves the window");
}
#[test]
fn the_hover_is_asked_of_each_frame_not_remembered() {
let mut hover = Hover::default();
hover.event(PointerKind::Move, BUTTON, false);
assert!(hover.target(&frame(0.0)).is_some(), "over the button");
assert_eq!(
hover.target(&frame(200.0)),
None,
"the button moved from under a still pointer"
);
}
}