libnotcurses_sys/widgets/menu/methods/menu.rs
1use core::ptr::null_mut;
2
3#[cfg(not(feature = "std"))]
4use alloc::{
5 format,
6 string::{String, ToString},
7};
8
9use crate::{
10 c_api::{self, ncmenu_create},
11 cstring, error, error_ref_mut, error_str, rstring,
12 widgets::{NcMenu, NcMenuOptions},
13 NcInput, NcPlane, NcResult,
14};
15
16#[allow(unused_imports)] // for doc comments
17use crate::widgets::{NcMenuItem, NcMenuSection};
18
19/// # `NcMenu` constructors & destructors
20impl NcMenu {
21 /// Creates an [`NcMenu`] with the specified options.
22 ///
23 /// Menus are currently bound to an overall [`Nc`][crate::Nc]
24 /// object (as opposed to a particular plane), and are implemented as
25 /// [`NcPlane`]s kept atop other NcPlanes.
26 ///
27 /// *C style function: [ncmenu_create()][c_api::ncmenu_create].*
28 pub fn new<'a>(plane: &mut NcPlane, options: &NcMenuOptions) -> NcResult<&'a mut Self> {
29 error_ref_mut![unsafe { ncmenu_create(plane, options) }, "Creating NcMenu"]
30 }
31
32 /// Destroys an `NcMenu` created with [`new`][NcMenu#method.new].
33 ///
34 /// *C style function: [ncmenu_destroy()][c_api::ncmenu_destroy].*
35 pub fn destroy(&mut self) {
36 unsafe { c_api::ncmenu_destroy(self) }
37 }
38}
39
40/// # `NcMenu` methods
41impl NcMenu {
42 /// Disables or enables an [`NcMenuItem`].
43 ///
44 /// *C style function: [ncmenu_item_set_status()][c_api::ncmenu_item_set_status].*
45 pub fn item_set_status(&mut self, section: &str, item: &str, enabled: bool) -> NcResult<()> {
46 let csection = cstring![section];
47 let citem = cstring![item];
48 error![
49 unsafe {
50 c_api::ncmenu_item_set_status(self, csection.as_ptr(), citem.as_ptr(), enabled)
51 },
52 &format!(
53 ".item_set_status({:?}, {:?}, {:?}, {})",
54 self, section, item, enabled
55 )
56 ]
57 }
58
59 /// Returns the [`NcMenuItem`] description
60 /// corresponding to the mouse `click`.
61 ///
62 /// The `NcMenuItem` must be on an actively unrolled section, and the click
63 /// must be in the area of a valid item.
64 ///
65 /// If `ninput` is provided, and the selected item has a shortcut,
66 /// it will be filled in with that shortcut.
67 ///
68 /// *C style function: [ncmenu_mouse_selected()][c_api::ncmenu_mouse_selected].*
69 pub fn mouse_selected(
70 &self,
71 click: NcInput,
72 shortcut: Option<&mut NcInput>,
73 ) -> NcResult<String> {
74 let ninput = if let Some(i) = shortcut { i as *mut _ } else { null_mut() };
75 error_str![
76 unsafe { c_api::ncmenu_mouse_selected(self, &click, ninput) },
77 "Getting NcMenuItem description"
78 ]
79 }
80
81 /// Moves to the next item within the currently unrolled section.
82 ///
83 /// If no section is unrolled, the first section will be unrolled.
84 ///
85 /// *C style function: [ncmenu_nextitem()][c_api::ncmenu_nextitem].*
86 pub fn nextitem(&mut self) -> NcResult<()> {
87 error![unsafe { c_api::ncmenu_nextitem(self) }]
88 }
89
90 /// Unrolls the next section (relative to current unrolled).
91 ///
92 /// If no section is unrolled, the first section will be unrolled.
93 ///
94 /// *C style function: [ncmenu_nextsection()][c_api::ncmenu_nextsection].*
95 pub fn nextsection(&mut self) -> NcResult<()> {
96 error![unsafe { c_api::ncmenu_nextsection(self) }]
97 }
98
99 /// Offers the `input` to this `NcMenu`.
100 ///
101 /// If it's relevant, this function returns true,
102 /// and the input ought not be processed further.
103 /// If it's irrelevant to the menu, false is returned.
104 ///
105 /// Relevant inputs include:
106 /// - mouse movement over a hidden menu
107 /// - a mouse click on a menu section (the section is unrolled)
108 /// - a mouse click outside of an unrolled menu (the menu is rolled up)
109 /// - left or right on an unrolled menu (navigates among sections)
110 /// - up or down on an unrolled menu (navigates among items)
111 /// - escape on an unrolled menu (the menu is rolled up)
112 ///
113 /// *C style function: [ncmenu_offer_input()][c_api::ncmenu_offer_input].*
114 pub fn offer_input(&mut self, input: NcInput) -> bool {
115 unsafe { c_api::ncmenu_offer_input(self, &input) }
116 }
117
118 /// Returns the [`NcPlane`] backing this `NcMenu`.
119 ///
120 /// *C style function: [ncmenu_plane()][c_api::ncmenu_plane].*
121 pub fn plane(&mut self) -> NcResult<&NcPlane> {
122 error_ref_mut![
123 unsafe { c_api::ncmenu_plane(self) },
124 "Getting the backing NcPlane"
125 ]
126 }
127
128 /// Moves to the previous item within the currently unrolled section.
129 ///
130 /// If no section is unrolled, the first section will be unrolled.
131 ///
132 /// *C style function: [ncmenu_previtem()][c_api::ncmenu_previtem].*
133 pub fn previtem(&mut self) -> NcResult<()> {
134 error![unsafe { c_api::ncmenu_previtem(self) }]
135 }
136
137 /// Unrolls the previous section (relative to current unrolled).
138 ///
139 /// If no section is unrolled, the first section will be unrolled.
140 ///
141 /// *C style function: [ncmenu_prevsection()][c_api::ncmenu_prevsection].*
142 pub fn prevsection(&mut self) -> NcResult<()> {
143 error![unsafe { c_api::ncmenu_prevsection(self) }]
144 }
145
146 /// Rolls up any unrolled [`NcMenuSection`]
147 /// and hides this `NcMenu` if using hiding.
148 ///
149 /// *C style function: [ncmenu_rollup()][c_api::ncmenu_rollup].*
150 pub fn rollup(&mut self) -> NcResult<()> {
151 error![unsafe { c_api::ncmenu_rollup(self) }]
152 }
153
154 /// Returns the selected item description, if there's an unrolled section.
155 ///
156 /// If `shortcut` is provided, and the selected item has a shortcut,
157 /// it will be filled in with that shortcut--this can allow faster matching.
158 ///
159 /// *C style function: [ncmenu_selected()][c_api::ncmenu_selected].*
160 pub fn selected(&mut self, shortcut: Option<&mut NcInput>) -> Option<String> {
161 let ninput = if let Some(i) = shortcut { i as *mut _ } else { null_mut() };
162 let res = unsafe { c_api::ncmenu_selected(self, ninput) };
163 if !res.is_null() {
164 Some(rstring![&*res].to_string())
165 } else {
166 None
167 }
168 }
169
170 /// Unrolls the specified [`NcMenuSection`],
171 /// making the menu visible if it was invisible
172 /// and rolling up any `NcMenuSection` that is already unrolled.
173 ///
174 /// *C style function: [ncmenu_unroll()][c_api::ncmenu_unroll].*
175 pub fn unroll(&mut self, sectionindex: u32) -> NcResult<()> {
176 error![unsafe { c_api::ncmenu_unroll(self, sectionindex as i32) }]
177 }
178}