use std::{collections::hash_map::DefaultHasher, hash::Hasher};
use super::MenuId;
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
#[derive(Debug, Clone)]
pub enum NativeImage {
Add,
Advanced,
Bluetooth,
Bookmarks,
Caution,
ColorPanel,
ColumnView,
Computer,
EnterFullScreen,
Everyone,
ExitFullScreen,
FlowView,
Folder,
FolderBurnable,
FolderSmart,
FollowLinkFreestanding,
FontPanel,
GoLeft,
GoRight,
Home,
IChatTheater,
IconView,
Info,
InvalidDataFreestanding,
LeftFacingTriangle,
ListView,
LockLocked,
LockUnlocked,
MenuMixedState,
MenuOnState,
MobileMe,
MultipleDocuments,
Network,
Path,
PreferencesGeneral,
QuickLook,
RefreshFreestanding,
Refresh,
Remove,
RevealFreestanding,
RightFacingTriangle,
Share,
Slideshow,
SmartBadge,
StatusAvailable,
StatusNone,
StatusPartiallyAvailable,
StatusUnavailable,
StopProgressFreestanding,
StopProgress,
TrashEmpty,
TrashFull,
User,
UserAccounts,
UserGroup,
UserGuest,
}
#[derive(Debug, Clone)]
pub enum MenuUpdate {
SetEnabled(bool),
SetTitle(String),
SetSelected(bool),
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
SetNativeImage(NativeImage),
}
pub trait TrayHandle {
fn set_icon(&self, icon: crate::Icon) -> crate::Result<()>;
fn update_item(&self, id: u16, update: MenuUpdate) -> crate::Result<()>;
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Menu<I: MenuId> {
pub items: Vec<MenuEntry<I>>,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Submenu<I: MenuId> {
pub title: String,
pub enabled: bool,
pub inner: Menu<I>,
}
impl<I: MenuId> Submenu<I> {
pub fn new<S: Into<String>>(title: S, menu: Menu<I>) -> Self {
Self {
title: title.into(),
enabled: true,
inner: menu,
}
}
}
impl<I: MenuId> Default for Menu<I> {
fn default() -> Self {
Self { items: Vec::new() }
}
}
impl<I: MenuId> Menu<I> {
pub fn new() -> Self {
Default::default()
}
pub fn add_item(mut self, item: CustomMenuItem<I>) -> Self {
self.items.push(MenuEntry::CustomItem(item));
self
}
pub fn add_native_item(mut self, item: MenuItem) -> Self {
self.items.push(MenuEntry::NativeItem(item));
self
}
pub fn add_submenu(mut self, submenu: Submenu<I>) -> Self {
self.items.push(MenuEntry::Submenu(submenu));
self
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct CustomMenuItem<I: MenuId> {
pub id: I,
pub title: String,
pub keyboard_accelerator: Option<String>,
pub enabled: bool,
pub selected: bool,
#[cfg(target_os = "macos")]
pub native_image: Option<NativeImage>,
}
impl<I: MenuId> CustomMenuItem<I> {
pub fn new<T: Into<String>>(id: I, title: T) -> Self {
Self {
id,
title: title.into(),
keyboard_accelerator: None,
enabled: true,
selected: false,
#[cfg(target_os = "macos")]
native_image: None,
}
}
pub fn accelerator<T: Into<String>>(mut self, accelerator: T) -> Self {
self.keyboard_accelerator.replace(accelerator.into());
self
}
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
pub fn native_image(mut self, image: NativeImage) -> Self {
self.native_image.replace(image);
self
}
pub fn disabled(mut self) -> Self {
self.enabled = false;
self
}
pub fn selected(mut self) -> Self {
self.selected = true;
self
}
#[doc(hidden)]
pub fn id_value(&self) -> u16 {
let mut s = DefaultHasher::new();
self.id.hash(&mut s);
s.finish() as u16
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct SystemTrayMenu<I: MenuId> {
pub items: Vec<SystemTrayMenuEntry<I>>,
}
impl<I: MenuId> Default for SystemTrayMenu<I> {
fn default() -> Self {
Self { items: Vec::new() }
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct SystemTraySubmenu<I: MenuId> {
pub title: String,
pub enabled: bool,
pub inner: SystemTrayMenu<I>,
}
impl<I: MenuId> SystemTraySubmenu<I> {
pub fn new<S: Into<String>>(title: S, menu: SystemTrayMenu<I>) -> Self {
Self {
title: title.into(),
enabled: true,
inner: menu,
}
}
}
impl<I: MenuId> SystemTrayMenu<I> {
pub fn new() -> Self {
Default::default()
}
pub fn add_item(mut self, item: CustomMenuItem<I>) -> Self {
self.items.push(SystemTrayMenuEntry::CustomItem(item));
self
}
pub fn add_native_item(mut self, item: SystemTrayMenuItem) -> Self {
self.items.push(SystemTrayMenuEntry::NativeItem(item));
self
}
pub fn add_submenu(mut self, submenu: SystemTraySubmenu<I>) -> Self {
self.items.push(SystemTrayMenuEntry::Submenu(submenu));
self
}
}
#[derive(Debug, Clone)]
pub enum SystemTrayMenuEntry<I: MenuId> {
CustomItem(CustomMenuItem<I>),
NativeItem(SystemTrayMenuItem),
Submenu(SystemTraySubmenu<I>),
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum SystemTrayMenuItem {
Separator,
}
#[derive(Debug, Clone)]
pub enum MenuEntry<I: MenuId> {
CustomItem(CustomMenuItem<I>),
NativeItem(MenuItem),
Submenu(Submenu<I>),
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum MenuItem {
About(String),
Hide,
Services,
HideOthers,
ShowAll,
CloseWindow,
Quit,
Copy,
Cut,
Undo,
Redo,
SelectAll,
Paste,
EnterFullScreen,
Minimize,
Zoom,
Separator,
}