use super::super::colors::{palette, AppearanceMode, WidgetState};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MenuItemKind {
Action,
Submenu,
Toggle { checked: bool },
Header,
Separator,
}
pub struct MenuTheme {
pub mode: AppearanceMode,
}
impl MenuTheme {
pub fn new(mode: AppearanceMode) -> Self {
Self { mode }
}
pub fn container_bg(&self) -> &'static str {
match self.mode {
AppearanceMode::Dark
| AppearanceMode::VibrantDark
| AppearanceMode::AccessibleDark
| AppearanceMode::AccessibleVibrantDark => "#242424D9", _ => "#F5F5F5E6", }
}
pub fn container_border_radius(&self) -> f64 {
6.0
}
pub fn container_padding(&self) -> (f64, f64) {
(4.0, 0.0) }
pub fn container_min_width(&self) -> f64 {
200.0
}
pub fn container_max_width(&self) -> f64 {
300.0
}
pub fn item_height(&self) -> f64 {
22.0
}
pub fn item_padding(&self) -> (f64, f64) {
(0.0, 12.0)
}
pub fn item_bg(&self, state: WidgetState) -> &'static str {
let p = palette(self.mode);
match state {
WidgetState::Normal | WidgetState::Focused => "transparent",
WidgetState::Hovered => p.selected_content_background, WidgetState::Pressed => {
match self.mode {
AppearanceMode::Dark
| AppearanceMode::VibrantDark
| AppearanceMode::AccessibleDark
| AppearanceMode::AccessibleVibrantDark => "#0055CC", _ => "#005ACC", }
}
WidgetState::Disabled => "transparent",
}
}
pub fn item_text_color(&self, state: WidgetState) -> &'static str {
let p = palette(self.mode);
match state {
WidgetState::Normal | WidgetState::Focused => p.label,
WidgetState::Hovered | WidgetState::Pressed => p.selected_menu_item_text, WidgetState::Disabled => p.disabled_control_text,
}
}
pub fn item_font(&self) -> &'static str {
"13px sans-serif"
}
pub fn item_shortcut_color(&self) -> &'static str {
palette(self.mode).secondary_label
}
pub fn item_chevron_color(&self) -> &'static str {
palette(self.mode).tertiary_label
}
pub fn separator_color(&self) -> &'static str {
palette(self.mode).separator
}
pub fn separator_height(&self) -> f64 {
1.0
}
pub fn separator_inset(&self) -> f64 {
8.0
}
pub fn header_text_color(&self) -> &'static str {
palette(self.mode).secondary_label
}
pub fn header_font(&self) -> &'static str {
"bold 11px sans-serif"
}
}
impl Default for MenuTheme {
fn default() -> Self {
Self::new(AppearanceMode::default())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_menu_theme_dark() {
let theme = MenuTheme::new(AppearanceMode::Dark);
assert_eq!(theme.container_bg(), "#242424D9");
assert_eq!(theme.container_border_radius(), 6.0);
assert_eq!(theme.item_height(), 22.0);
}
#[test]
fn test_menu_theme_light() {
let theme = MenuTheme::new(AppearanceMode::Light);
assert_eq!(theme.container_bg(), "#F5F5F5E6");
assert_eq!(theme.container_min_width(), 200.0);
assert_eq!(theme.container_max_width(), 300.0);
}
#[test]
fn test_menu_item_bg_states() {
let theme = MenuTheme::new(AppearanceMode::Dark);
assert_eq!(theme.item_bg(WidgetState::Normal), "transparent");
assert_ne!(theme.item_bg(WidgetState::Hovered), "transparent");
}
#[test]
fn test_menu_item_text_color_hovered() {
let theme = MenuTheme::new(AppearanceMode::Dark);
let p = palette(AppearanceMode::Dark);
assert_eq!(
theme.item_text_color(WidgetState::Hovered),
p.selected_menu_item_text
);
}
#[test]
fn test_separator_styling() {
let theme = MenuTheme::default();
assert_eq!(theme.separator_height(), 1.0);
assert_eq!(theme.separator_inset(), 8.0);
}
}