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}