use crate::core::{Color, Rect};
use crate::render::{RenderCommand, RenderContext};
use crate::style::MenuEffects;
pub(crate) const SUBMENU_HOVER_DELAY_MS: u32 = 300;
#[cfg(test)]
thread_local! {
static TEST_EFFECTS: core::cell::Cell<Option<MenuEffects>> = const { core::cell::Cell::new(None) };
}
#[cfg(test)]
pub(crate) fn with_test_effects<R>(effects: MenuEffects, f: impl FnOnce() -> R) -> R {
let previous = TEST_EFFECTS.with(|cell| cell.replace(Some(effects)));
let result = f();
TEST_EFFECTS.with(|cell| cell.set(previous));
result
}
pub(crate) fn current() -> MenuEffects {
#[cfg(test)]
{
TEST_EFFECTS.with(|cell| cell.get()).unwrap_or_else(MenuEffects::legacy)
}
#[cfg(not(test))]
{
#[cfg(feature = "advanced-widgets")]
{
crate::menu_config::current_effects()
}
#[cfg(not(feature = "advanced-widgets"))]
{
MenuEffects::legacy()
}
}
}
pub(crate) fn paint_popup_shadow(context: &mut RenderContext, rect: Rect, effects: &MenuEffects) {
if !effects.shadows {
return;
}
let blur_radius = if effects.blur {
12
} else if effects.hardware_acceleration {
6
} else {
0
};
context.execute_command(RenderCommand::BoxShadow {
rect,
color: Color::rgba(0, 0, 0, 120),
offset_x: 0,
offset_y: 3,
blur_radius,
spread: 0,
});
}
pub(crate) fn popup_face(face: Color, effects: &MenuEffects) -> Color {
if effects.transparency {
face.with_alpha(230)
} else {
face
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::render::PaintBackend;
fn render_shadow(effects: &MenuEffects) -> String {
let mut backend = crate::render::SvgPaintBackend::new(crate::core::Size::new(200, 200));
backend.begin_frame(Color::WHITE);
let mut context = RenderContext::new(&mut backend);
paint_popup_shadow(&mut context, Rect::new(10, 10, 50, 50), effects);
backend.end_frame();
backend.finish()
}
#[test]
fn the_popup_material_is_opt_in() {
let face = Color::rgb(40, 60, 80);
let mut effects = MenuEffects::legacy();
assert_eq!(popup_face(face, &effects), face, "the legacy policy changes no pixel");
effects.transparency = true;
assert_eq!(popup_face(face, &effects).a, 230, "the material alpha is applied");
}
#[test]
fn a_shadow_needs_the_policy() {
let plain = render_shadow(&MenuEffects::legacy());
let mut effects = MenuEffects::legacy();
effects.shadows = true;
let shadowed = render_shadow(&effects);
assert_ne!(plain, shadowed, "enabling shadows must paint something");
}
}