Hovering
The HoverPlugin
listens to the Mouse
global, detecting what widgets the mouse is currently hovering over. This can be used for animations, click detection, and in many other scenarios where mouse interaction is required.
Motivation and Usage
Without user interaction, a user interface isn't exactly, well, a user interface. There's also great value in reducing exact mouse position events into a single listener that can then "broadcast" coarser events to any widget that cares about them. Imagine if every button in your widget tree was getting updated every single time the mouse position changed—it would cause an unfortunate amount of update calls for an event that, realistically, doesn't need to be that fine-grained.
So, the HoverPlugin
solves that problem. It consumes mouse positions and writes to the Hovering
global only when the widget you're hovering over changes, saving CPU and reducing the errors that could occur if every widget was implementing this functionality themselves.
To use it, it's highly recommended to listen to it within a computed value, so your widget is only rebuilt when its hover state changes.
#[functional_widget]
fn hovering_widget(ctx: &BuildContext) -> BuildResult {
let is_hovering = ctx.computed(|ctx| {
// We use `try_use_global` here, since we don't want to test for hovering if the plugin isn't loaded
if let Some(hovering) = ctx.try_use_global::<Hovering>() {
if hovering.read().is_hovering(ctx) {
true
}
}
false
});
build! {
if is_hovering {
Button {
layout: Layout {
sizing: Sizing::Set { width: 64.0, height 32.0 }
}
}
}else{
Button {
layout: Layout {
sizing: Sizing::Set { width: 32.0, height 64.0 }
}
}
}
}
}
No matter how often the Hovering
global changes, the widget will only be rebuilt when is_hovering
matches and the function returns true
. If you didn't use the computed value, the widget would be rebuilt every time the currently hovered widget changed, which wouldn't be good.