1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::rc::{Rc, Weak};
use nappgui_sys::{
menu_add_item, menu_count, menu_create, menu_del_item, menu_destroy, menu_get_item,
menu_ins_item, menu_is_menubar, menu_launch, menu_off_items, V2Df,
};
use crate::gui::{window::WindowTrait, MenuItemTrait};
use super::MenuItem;
/// The menu trait.
pub trait MenuTrait {
/// Returns a raw pointer to the menu object.
fn as_ptr(&self) -> *mut nappgui_sys::Menu;
/// Add an item at the end of the menu.
fn add_item<T>(&self, item: T)
where
T: MenuItemTrait,
{
unsafe { menu_add_item(self.as_ptr(), item.as_ptr()) };
}
/// Insert an item in an arbitrary position of the menu.
fn insert_item<T>(&self, index: u32, item: T)
where
T: MenuItemTrait,
{
unsafe { menu_ins_item(self.as_ptr(), index, item.as_ptr()) };
}
/// Remove an item from the menu.
///
/// # Remark
/// The element will be destroyed and cannot be reused. If has a submenu associated,
/// it will also be destroyed recursively.
fn delete_item(&self, index: u32) {
unsafe { menu_del_item(self.as_ptr(), index) };
}
/// Launch a menu as secondary or PopUp.
fn launch<T>(&self, window: &T, x: f32, y: f32)
where
T: WindowTrait,
{
let position = V2Df { x, y };
unsafe { menu_launch(self.as_ptr(), window.as_ptr(), position) };
}
/// Set status ekGUI_OFF for all menu items.
fn off_items(&self) {
unsafe { menu_off_items(self.as_ptr()) };
}
/// Get the number of items.
fn count(&self) -> usize {
unsafe { menu_count(self.as_ptr()) as _ }
}
/// Get an item from the menu.
fn get_item(&self, index: u32) -> Option<MenuItem> {
let item = unsafe { menu_get_item(self.as_ptr(), index) };
if item.is_null() {
None
} else {
Some(MenuItem { inner: item })
}
}
/// Returns TRUE if the menu is currently established as a menu bar.
fn is_menubar(&self) -> bool {
(unsafe { menu_is_menubar(self.as_ptr()) }) != 0
}
}
/// The inner type of menu.
#[doc(hidden)]
#[repr(transparent)]
pub struct MenuInner {
pub(crate) inner: *mut nappgui_sys::Menu,
}
impl MenuTrait for MenuInner {
fn as_ptr(&self) -> *mut nappgui_sys::Menu {
self.inner
}
}
/// A Menu is a type of control that integrates a series of options, also called items or Menuitems.
/// Each of them consists of a short text, optionally an icon and optionally also a keyboard shortcut,
/// such as the classic Ctrl+C/Ctrl+V to copy and paste. Additionally, an item can house a submenu
/// forming a hierarchy with different levels of depth. In Products you have an application that uses
/// menus and in Hello dynamic Menu! an example of adding or eliminating items at runtime.
pub struct Menu {
pub(crate) inner: Rc<MenuInner>,
}
impl Menu {
/// Create a new menu.
pub fn new() -> Self {
let menu = unsafe { menu_create() };
Self {
inner: Rc::new(MenuInner { inner: menu }),
}
}
/// Get the weak reference of the menu.
pub fn as_weak(&self) -> Weak<MenuInner> {
Rc::downgrade(&self.inner)
}
}
impl MenuTrait for Menu {
fn as_ptr(&self) -> *mut nappgui_sys::Menu {
self.inner.as_ptr()
}
}
impl MenuTrait for Weak<MenuInner> {
fn as_ptr(&self) -> *mut nappgui_sys::Menu {
let menu = self.upgrade().unwrap();
menu.inner
}
}
impl Drop for Menu {
fn drop(&mut self) {
unsafe { menu_destroy(&mut self.as_ptr()) };
}
}