zng_view_api/menu.rs
1//! Application system menu.
2
3use bitflags::bitflags;
4use zng_txt::Txt;
5
6use crate::image::ImageId;
7
8/// Represents a menu command or submenu header.
9#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
10#[non_exhaustive]
11pub enum MenuItem {
12 /// Clickable action.
13 #[non_exhaustive]
14 Command {
15 /// Unique ID for this command within all menu items in the app.
16 ///
17 /// If this id is empty the menu item is disabled.
18 id: Txt,
19 /// Display text.
20 label: Txt,
21 },
22 /// Submenu.
23 #[non_exhaustive]
24 SubMenu {
25 /// Display text.
26 label: Txt,
27 /// Children items.
28 children: Vec<MenuItem>,
29 },
30 /// Separation line.
31 Separator,
32}
33impl MenuItem {
34 /// New command.
35 pub fn command(id: impl Into<Txt>, label: impl Into<Txt>) -> Self {
36 Self::Command {
37 id: id.into(),
38 label: label.into(),
39 }
40 }
41
42 /// New submenu.
43 pub fn sub_menu(label: impl Into<Txt>, children: Vec<MenuItem>) -> Self {
44 Self::SubMenu {
45 label: label.into(),
46 children,
47 }
48 }
49}
50
51/// Represents a system application menu.
52#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
53#[non_exhaustive]
54pub struct AppMenu {
55 /// The menu items.
56 ///
57 /// If empty no application menu is set.
58 pub children: Vec<MenuItem>,
59}
60impl AppMenu {
61 /// New.
62 pub fn new(children: Vec<MenuItem>) -> Self {
63 Self { children }
64 }
65
66 /// Value that represents no app menu.
67 pub fn none() -> Self {
68 Self::new(vec![])
69 }
70}
71
72/// Represents a *tray icon* status indicator.
73#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
74#[non_exhaustive]
75pub struct TrayIcon {
76 /// Icon image.
77 ///
78 /// The tray icon will only be inserted when this image is valid and loaded.
79 pub icon: ImageId,
80 /// Optional context menu.
81 ///
82 /// If not empty a context menu shows on context clock.
83 pub context_menu: Vec<MenuItem>,
84 /// A command ID for a primary click on the icon.
85 ///
86 /// If set an [`Event::MenuCommand`] notifies on click, otherwise the context menu also opens on primary click.
87 ///
88 /// [`Event::MenuCommand`]: crate::types::Event::MenuCommand
89 pub primary_command_id: Txt,
90}
91impl TrayIcon {
92 /// New.
93 pub fn new(icon: ImageId, context_menu: Vec<MenuItem>) -> Self {
94 Self {
95 icon,
96 context_menu,
97 primary_command_id: Txt::from_static(""),
98 }
99 }
100
101 /// Value that indicates no tray icon.
102 pub fn none() -> Self {
103 Self::new(ImageId::INVALID, vec![])
104 }
105}
106
107bitflags! {
108 /// System menu capability.
109 #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
110 pub struct MenuCapability: u32 {
111 /// View-process can set application menu items.
112 ///
113 /// The application menu is shown outside the app windows, usually at the top of the main screen in macOS and Gnome desktops.
114 const APP_MENU = 1;
115 /// View-process can set tray icon with context menu.
116 ///
117 /// This is a small status indicator icon displayed near the notifications area.
118 const TRAY_ICON = 1 << 1;
119 }
120}