use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use crate::{KeyData, Offset, ViewId};
pub type MenuId = u32;
#[derive(Clone, Debug, PartialEq)]
pub enum MenuEntry {
Submenu {
id: MenuId,
label: String,
enabled: bool,
entries: Vec<MenuEntry>,
},
Item { id: MenuId, item: MenuItem },
Provided {
id: MenuId,
item: ProvidedItem,
enabled: bool,
},
Separator,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MenuItem {
pub label: String,
pub enabled: bool,
pub check: MenuItemCheck,
pub shortcut: Option<MenuShortcut>,
pub icon: Option<IconImage>,
}
impl MenuItem {
pub fn new(label: impl Into<String>) -> MenuItem {
MenuItem {
label: label.into(),
enabled: true,
check: MenuItemCheck::Plain,
shortcut: None,
icon: None,
}
}
pub fn enabled(mut self, enabled: bool) -> MenuItem {
self.enabled = enabled;
self
}
pub fn check(mut self, check: MenuItemCheck) -> MenuItem {
self.check = check;
self
}
pub fn shortcut(mut self, shortcut: MenuShortcut) -> MenuItem {
self.shortcut = Some(shortcut);
self
}
pub fn icon(mut self, icon: IconImage) -> MenuItem {
self.icon = Some(icon);
self
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MenuItemCheck {
Plain,
Checkbox(CheckState),
Radio(bool),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CheckState {
Off,
On,
Mixed,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct MenuShortcut {
pub key: u64,
pub modifiers: ShortcutModifiers,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ShortcutModifiers {
pub meta: bool,
pub control: bool,
pub alt: bool,
pub shift: bool,
}
#[derive(Clone, PartialEq)]
pub struct IconImage {
pub width: u32,
pub height: u32,
pub rgba: Arc<[u8]>,
pub template: bool,
}
impl fmt::Debug for IconImage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IconImage")
.field("width", &self.width)
.field("height", &self.height)
.field("template", &self.template)
.finish_non_exhaustive()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ProvidedItem {
About,
Services,
Hide,
HideOthers,
ShowAll,
Quit,
Minimize,
Zoom,
ToggleFullScreen,
BringAllToFront,
Undo,
Redo,
Cut,
Copy,
Paste,
SelectAll,
Delete,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EditCommand {
Undo,
Redo,
SelectAll,
Delete,
}
pub trait MenuBar {
fn set_menus(&self, menus: &[MenuEntry]);
fn perform_key_equivalent(&self, key: &KeyData) -> bool;
}
pub trait PopupMenus {
fn show(&self, view: ViewId, at: Offset, menu: &[MenuEntry]) -> PopupMenuFuture;
}
pub type PopupMenuFuture = Pin<Box<dyn Future<Output = Option<MenuId>>>>;
pub trait DockMenu {
fn set_menu(&self, menu: &[MenuEntry]);
}
pub trait TrayIcons {
fn add(&self, image: &IconImage, tooltip: Option<&str>) -> TrayIconFuture;
}
pub type TrayIconFuture = Pin<Box<dyn Future<Output = Result<Box<dyn TrayIcon>, TrayIconError>>>>;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TrayIconError {
Failed(String),
}
impl fmt::Display for TrayIconError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TrayIconError::Failed(reason) => write!(f, "the tray icon did not appear: {reason}"),
}
}
}
impl std::error::Error for TrayIconError {}
pub type TrayIconId = u64;
pub trait TrayIcon {
fn id(&self) -> TrayIconId;
fn set_image(&self, image: &IconImage);
fn set_tooltip(&self, tooltip: Option<&str>);
fn attached_menu(&self) -> Option<&dyn AttachedMenu>;
fn menu_at_icon(&self) -> Option<&dyn MenuAtIcon>;
}
pub trait AttachedMenu {
fn set_menu(&self, menu: &[MenuEntry]);
}
pub trait MenuAtIcon {
fn show(&self, menu: &[MenuEntry]) -> PopupMenuFuture;
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TrayIconEvent {
Activated {
position: Offset,
},
ContextMenuRequested {
position: Offset,
},
SecondaryActivated {
position: Offset,
},
DoubleClicked,
Scrolled {
delta: f64,
},
MenuSelected(MenuId),
}