use frus_core::{Color, Point, Rect, Scene};
use crate::interaction::Status;
use crate::theme::Theme;
use crate::widgetstate::{WidgetState, WidgetStates};
pub(crate) const SPLASH: f32 = 20.0;
pub(crate) fn overlay(theme: &Theme, states: WidgetStates) -> Color {
let c = &theme.scheme;
let pick = |press: Color, hover: Color, focus: Color| {
if states.contains(WidgetState::Pressed) {
press.with_alpha(0.1)
} else if states.contains(WidgetState::Hovered) {
hover.with_alpha(0.08)
} else if states.contains(WidgetState::Focused) {
focus.with_alpha(0.1)
} else {
Color::TRANSPARENT
}
};
if states.contains(WidgetState::Selected) {
pick(c.on_surface, c.primary, c.primary)
} else {
pick(c.primary, c.on_surface, c.on_surface)
}
}
pub(crate) fn paint_halos(
scene: &mut Scene,
centre: Point,
radius: f32,
status: &Status,
colour_for: impl Fn(WidgetState) -> Color,
) {
let o = status.opacity;
let mut halo = |state: WidgetState, amount: f32, r: f32| {
if amount <= 0.0 || r <= 0.0 {
return;
}
let c = colour_for(state);
if c.a > 0.0 {
scene.draw_rect(
Rect::new(centre.x - r, centre.y - r, 2.0 * r, 2.0 * r),
c.with_alpha(c.a * amount.clamp(0.0, 1.0)).fade(o),
r,
0.0,
Color::TRANSPARENT,
);
}
};
halo(WidgetState::Hovered, status.hover_progress, radius);
halo(WidgetState::Focused, status.focus_progress, radius);
let press = status.press_progress.clamp(0.0, 1.0);
halo(WidgetState::Pressed, 1.0, radius * press);
}
#[cfg(test)]
mod tests {
use super::overlay;
use crate::theme::Theme;
use crate::widgetstate::{WidgetState, WidgetStates};
#[test]
fn the_halo_colours_are_the_reference_s() {
let theme = Theme::dark();
let c = &theme.scheme;
let on = |s: WidgetState| overlay(&theme, WidgetState::Selected | s);
let off = |s: WidgetState| overlay(&theme, WidgetStates::of(s));
assert_eq!(on(WidgetState::Pressed), c.on_surface.with_alpha(0.1));
assert_eq!(on(WidgetState::Hovered), c.primary.with_alpha(0.08));
assert_eq!(on(WidgetState::Focused), c.primary.with_alpha(0.1));
assert_eq!(off(WidgetState::Pressed), c.primary.with_alpha(0.1));
assert_eq!(off(WidgetState::Hovered), c.on_surface.with_alpha(0.08));
assert_eq!(off(WidgetState::Focused), c.on_surface.with_alpha(0.1));
assert_eq!(
overlay(&theme, WidgetStates::EMPTY).a,
0.0,
"nothing at rest"
);
}
}