From a880eaf018f3e3b9da9472217d1823a2befb706e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?joseLu=C3=ADs?= Date: Sat, 26 Dec 2020 20:29:06 +0100 Subject: [PATCH] rust: new NcMenu PoC example & more error refactoring. - new example poc-menu (WIP). - improve constructors for NcMenu*. - divide NcMenu* methods into submodules. - fix return type for NcPlane constructors. - use NcResult on functions returning references. - fix a couple of Notcurses methods. - add more NcChannelPair methods. - refactor NcInput constructors. - rename error_ptr![] to error_ref_mut![] - new macro cstring_mut![]. - new error_ref![] macro. - update examples & tests. - bump version in readme. --- rust/README.md | 2 +- rust/examples/full-input.rs | 2 +- rust/examples/poc-cjkscroll.rs | 2 +- rust/src/cells/test/methods.rs | 2 +- rust/src/channel/methods.rs | 16 +++ rust/src/channel/mod.rs | 4 +- rust/src/input/mod.rs | 53 +++++++++- rust/src/lib.rs | 2 +- rust/src/macros.rs | 41 +++++++- rust/src/notcurses/methods.rs | 24 ++--- rust/src/notcurses/reimplemented.rs | 28 +++--- rust/src/plane/methods.rs | 33 +++---- .../menu/{methods.rs => methods/menu.rs} | 98 +++---------------- rust/src/widgets/menu/methods/mod.rs | 53 ++++++++++ rust/src/widgets/menu/methods/options.rs | 70 +++++++++++++ rust/src/widgets/menu/mod.rs | 9 +- rust/src/widgets/reader/methods.rs | 4 +- 17 files changed, 302 insertions(+), 141 deletions(-) rename rust/src/widgets/menu/{methods.rs => methods/menu.rs} (68%) create mode 100644 rust/src/widgets/menu/methods/mod.rs create mode 100644 rust/src/widgets/menu/methods/options.rs diff --git a/rust/README.md b/rust/README.md index 735ba2f3a..e48d86a8f 100644 --- a/rust/README.md +++ b/rust/README.md @@ -2,5 +2,5 @@ [![Crate](https://img.shields.io/crates/v/libnotcurses-sys.svg)](https://crates.io/crates/libnotcurses-sys) [![API](https://docs.rs/libnotcurses-sys/badge.svg)](https://dankamongmen.github.io/notcurses/rustdoc/libnotcurses_sys/) -[![dependency status](https://deps.rs/crate/libnotcurses-sys/2.1.1/status.svg)](https://deps.rs/crate/libnotcurses-sys/2.1.1) +[![dependency status](https://deps.rs/crate/libnotcurses-sys/2.1.2/status.svg)](https://deps.rs/crate/libnotcurses-sys/2.1.2) [![MSRV: 1.47.0](https://flat.badgen.net/badge/MSRV/1.47.0/purple)](https://blog.rust-lang.org/2020/10/08/Rust-1.47.html) diff --git a/rust/examples/full-input.rs b/rust/examples/full-input.rs index 76569069a..63cb5f08b 100644 --- a/rust/examples/full-input.rs +++ b/rust/examples/full-input.rs @@ -18,7 +18,7 @@ fn main() -> NcResult<()> { println!("Exit with F1\n"); - let mut input = NcInput::new(); + let mut input = NcInput::new_empty(); loop { let key = notcurses_getc_nblock(nc, &mut input); diff --git a/rust/examples/poc-cjkscroll.rs b/rust/examples/poc-cjkscroll.rs index 197929038..059360b58 100644 --- a/rust/examples/poc-cjkscroll.rs +++ b/rust/examples/poc-cjkscroll.rs @@ -5,7 +5,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { let nc = Notcurses::new()?; - let plane = nc.stdplane(); + let plane = nc.stdplane()?; plane.set_scrolling(true); let mut wc = '\u{4e00}'; // 一 diff --git a/rust/src/cells/test/methods.rs b/rust/src/cells/test/methods.rs index b4d5f63e6..71444258b 100644 --- a/rust/src/cells/test/methods.rs +++ b/rust/src/cells/test/methods.rs @@ -11,7 +11,7 @@ fn constructors() -> crate::NcResult<()> { let _c2 = NcCell::with_char7b('C'); let nc = Notcurses::new()?; - let plane = NcPlane::new(nc, 0, 0, 10, 10); + let plane = NcPlane::new(nc, 0, 0, 10, 10)?; let _c3 = NcCell::with_char('௵', plane); nc.stop()?; Ok(()) diff --git a/rust/src/channel/methods.rs b/rust/src/channel/methods.rs index babdfee12..d183be853 100644 --- a/rust/src/channel/methods.rs +++ b/rust/src/channel/methods.rs @@ -31,6 +31,8 @@ pub trait NcChannelPairMethods { fn bg_alpha(&self) -> NcAlphaBits; fn set_fg_alpha(&mut self, alpha: NcAlphaBits); fn set_bg_alpha(&mut self, alpha: NcAlphaBits); + fn set_fg_rgb(&mut self, alpha: NcAlphaBits); + fn set_bg_rgb(&mut self, alpha: NcAlphaBits); } // NcChannel ------------------------------------------------------------------- @@ -187,4 +189,18 @@ impl NcChannelPairMethods for NcChannelPair { fn set_bg_alpha(&mut self, alpha: NcAlphaBits) { crate::channels_set_bg_alpha(self, alpha) } + + /// Sets the foreground [NcRgb]. + /// + /// *C style function: [channels_set_fg_rgb()][crate::channels_set_fg_rgb].* + fn set_fg_rgb(&mut self, rgb: NcRgb) { + crate::channels_set_fg_rgb(self, rgb) + } + + /// Sets the background [NcRgb]. + /// + /// *C style function: [channels_set_bg_rgb()][crate::channels_set_bg_rgb].* + fn set_bg_rgb(&mut self, rgb: NcRgb) { + crate::channels_set_bg_rgb(self, rgb) + } } diff --git a/rust/src/channel/mod.rs b/rust/src/channel/mod.rs index 30656c6ac..60ac98c92 100644 --- a/rust/src/channel/mod.rs +++ b/rust/src/channel/mod.rs @@ -49,14 +49,14 @@ //W+ channels_set_bg_alpha // + channels_set_bg_default // # channels_set_bg_palindex -// + channels_set_bg_rgb +//W+ channels_set_bg_rgb // + channels_set_bg_rgb8 // X channels_set_bg_rgb8_clipped // # channels_set_fchannel //W+ channels_set_fg_alpha // + channels_set_fg_default // # channels_set_fg_palindex -// + channels_set_fg_rgb +//W+ channels_set_fg_rgb // + channels_set_fg_rgb8 // X channels_set_fg_rgb8_clipped diff --git a/rust/src/input/mod.rs b/rust/src/input/mod.rs index e203401f4..1acf24342 100644 --- a/rust/src/input/mod.rs +++ b/rust/src/input/mod.rs @@ -9,6 +9,8 @@ // + nckey_mouse_p // + nckey_supppuab_p +use crate::NcDimension; + mod keycodes; pub use keycodes::*; @@ -50,7 +52,8 @@ pub const fn ncinput_equal_p(n1: NcInput, n2: NcInput) -> bool { /// New NcInput. impl NcInput { - pub const fn new() -> NcInput { + /// New empty NcInput. + pub const fn new_empty() -> NcInput { NcInput { id: 0, y: 0, @@ -61,6 +64,54 @@ impl NcInput { seqnum: 0, } } + + /// New NcInput, expecting all the arguments. + pub const fn with_all_args( + id: char, + x: Option, + y: Option, + alt: bool, + shift: bool, + ctrl: bool, + seqnum: u64, + ) -> NcInput { + let (ix, iy); + if let Some(x) = x { + ix = x as i32 + } else { + ix = -1 + }; + if let Some(y) = y { + iy = y as i32 + } else { + iy = -1 + }; + + NcInput { + id: id as u32, + y: ix, + x: iy, + alt, + shift, + ctrl, + seqnum, + } + } + + /// New NcInput with alt key. + pub const fn with_alt(id: char) -> NcInput { + Self::with_all_args(id, None, None, true, false, false, 0) + } + + /// New NcInput with shift key. + pub const fn with_shift(id: char) -> NcInput { + Self::with_all_args(id, None, None, false, true, false, 0) + } + + /// New NcInput with ctrl key. + pub const fn with_ctrl(id: char) -> NcInput { + Self::with_all_args(id, None, None, false, false, true, 0) + } } /// Is this [char] a Supplementary Private Use Area-B codepoint? diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 9b355de9c..76eaffd80 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -15,7 +15,7 @@ //! //! fn main() -> NcResult<()> { //! let nc = Notcurses::without_altscreen()?; -//! let plane = nc.stdplane(); +//! let plane = nc.stdplane()?; //! plane.putstr("hello world"); //! nc.render(); //! nc.stop()?; diff --git a/rust/src/macros.rs b/rust/src/macros.rs index acf78bcec..7921fcb09 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -67,9 +67,9 @@ macro_rules! fsleep { }; } -// General Utility Macros ------------------------------------------------------ +// String & Print Macros ------------------------------------------------------- -/// Converts an `&str` into `*mut CString`, for when a `*const c_char` is needed. +/// Converts an `&str` into `*const c_char`. #[macro_export] macro_rules! cstring { ($s:expr) => { @@ -77,6 +77,14 @@ macro_rules! cstring { }; } +/// Converts an `&str` into `*mut c_char`. +#[macro_export] +macro_rules! cstring_mut { + ($s:expr) => { + std::ffi::CString::new($s).unwrap().into_raw(); + }; +} + /// Converts a `*const c_char` into an `&str`. #[macro_export] macro_rules! rstring { @@ -126,16 +134,39 @@ macro_rules! error { }; } +/// Returns an Ok(&T) from a `*const T` pointer, +/// or an Err([NcError]) if the pointer is null. +/// +/// In other words: +/// Returns Ok(&*`$ptr`) if `$ptr` != `null()`, otherwise returns +/// Err([NcError]]::[new][NcError#method.new]([NCRESULT_ERR], `$msg`)). +/// +/// `$msg` is optional. By default it will be an empty `&str` `""`. +#[macro_export] +macro_rules! error_ref { + ($ptr:expr, $msg:expr) => { + if $ptr != core::ptr::null() { + #[allow(unused_unsafe)] + return Ok(unsafe { &*$ptr }); + } else { + return Err(crate::NcError::with_msg(crate::NCRESULT_ERR, $msg)); + } + }; + ($ptr:expr) => { + error_ref![$ptr, ""]; + }; +} + /// Returns an Ok(&mut T) from a `*mut T` pointer, /// or an Err([NcError]) if the pointer is null. /// /// In other words: -/// Returns Ok(&mut *`$ptr`) if `$ptr` != `null()`, otherwise returns +/// Returns Ok(&mut *`$ptr`) if `$ptr` != `null_mut()`, otherwise returns /// Err([NcError]]::[new][NcError#method.new]([NCRESULT_ERR], `$msg`)). /// /// `$msg` is optional. By default it will be an empty `&str` `""`. #[macro_export] -macro_rules! error_ptr { +macro_rules! error_ref_mut { ($ptr:expr, $msg:expr) => { if $ptr != core::ptr::null_mut() { #[allow(unused_unsafe)] @@ -145,7 +176,7 @@ macro_rules! error_ptr { } }; ($ptr:expr) => { - error_ptr![$ptr, ""]; + error_ref_mut![$ptr, ""]; }; } diff --git a/rust/src/notcurses/methods.rs b/rust/src/notcurses/methods.rs index 074b2f417..bfb86f174 100644 --- a/rust/src/notcurses/methods.rs +++ b/rust/src/notcurses/methods.rs @@ -3,10 +3,10 @@ use core::ptr::{null, null_mut}; use crate::{ - cstring, error, notcurses_init, rstring, NcAlign, NcBlitter, NcChannelPair, NcDimension, NcEgc, - NcError, NcFile, NcInput, NcLogLevel, NcPlane, NcResult, NcScale, NcSignalSet, NcStats, - NcStyleMask, NcTime, Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN, - NCOPTION_SUPPRESS_BANNERS, NCRESULT_ERR, + cstring, error, error_ref_mut, notcurses_init, rstring, NcAlign, NcBlitter, NcChannelPair, + NcDimension, NcEgc, NcError, NcFile, NcInput, NcLogLevel, NcPlane, NcResult, NcScale, + NcSignalSet, NcStats, NcStyleMask, NcTime, Notcurses, NotcursesOptions, + NCOPTION_NO_ALTERNATE_SCREEN, NCOPTION_SUPPRESS_BANNERS, NCRESULT_ERR, }; /// # `NotcursesOptions` Constructors @@ -502,11 +502,11 @@ impl Notcurses { /// *C style function: [notcurses_stddim_yx()][crate::notcurses_stddim_yx].* #[inline] pub fn stddim_yx<'a>( - nc: &'a mut Notcurses, + &'a mut self, y: &mut NcDimension, x: &mut NcDimension, - ) -> &'a mut NcPlane { - crate::notcurses_stddim_yx(nc, y, x) + ) -> NcResult<&'a mut NcPlane> { + crate::notcurses_stddim_yx(self, y, x) } /// [stdplane_const()][Notcurses#method.stdplane_const], plus free @@ -515,11 +515,11 @@ impl Notcurses { /// *C style function: [notcurses_stddim_yx()][crate::notcurses_stddim_yx].* #[inline] pub fn stddim_yx_const<'a>( - nc: &'a Notcurses, + &'a self, y: &mut NcDimension, x: &mut NcDimension, - ) -> &'a NcPlane { - crate::notcurses_stddim_yx_const(nc, y, x) + ) -> NcResult<&'a NcPlane> { + crate::notcurses_stddim_yx_const(self, y, x) } /// Returns a mutable reference to the standard [NcPlane] for this terminal. @@ -528,8 +528,8 @@ impl Notcurses { /// uppermost, leftmost cell. /// /// *C style function: [notcurses_stdplane()][crate::notcurses_stdplane].* - pub fn stdplane<'a>(&mut self) -> &'a mut NcPlane { - unsafe { &mut *crate::notcurses_stdplane(self) } + pub fn stdplane<'a>(&mut self) -> NcResult<&'a mut NcPlane> { + error_ref_mut![unsafe { crate::notcurses_stdplane(self) }] } /// Returns a reference to the standard [NcPlane] for this terminal. diff --git a/rust/src/notcurses/reimplemented.rs b/rust/src/notcurses/reimplemented.rs index 928be7c64..f16aa6349 100644 --- a/rust/src/notcurses/reimplemented.rs +++ b/rust/src/notcurses/reimplemented.rs @@ -1,10 +1,10 @@ //! `notcurses_*` reimplemented functions. -use core::ptr::null; +use core::ptr::{null, null_mut}; use crate::{ - NcAlign, NcDimension, NcInput, NcOffset, NcPlane, NcSignalSet, NcTime, Notcurses, - NCALIGN_CENTER, NCALIGN_LEFT, NCALIGN_RIGHT, NCRESULT_MAX, + NcAlign, NcDimension, NcError, NcInput, NcOffset, NcPlane, NcResult, NcSignalSet, NcTime, + Notcurses, NCALIGN_CENTER, NCALIGN_LEFT, NCALIGN_RIGHT, NCRESULT_ERR, NCRESULT_MAX, }; /// Returns the offset into `availcols` at which `cols` ought be output given @@ -73,12 +73,15 @@ pub fn notcurses_stddim_yx<'a>( nc: &'a mut Notcurses, y: &mut NcDimension, x: &mut NcDimension, -) -> &'a mut NcPlane { +) -> NcResult<&'a mut NcPlane> { unsafe { - let s = crate::notcurses_stdplane(nc); - crate::ncplane_dim_yx(s, &mut (*y as i32), &mut (*x as i32)); - &mut *s + let sp = crate::notcurses_stdplane(nc); + if sp != null_mut() { + crate::ncplane_dim_yx(sp, &mut (*y as i32), &mut (*x as i32)); + return Ok(&mut *sp); + } } + Err(NcError::new(NCRESULT_ERR)) } /// [notcurses_stdplane_const()][crate::notcurses_stdplane_const], plus free @@ -90,12 +93,15 @@ pub fn notcurses_stddim_yx_const<'a>( nc: &'a Notcurses, y: &mut NcDimension, x: &mut NcDimension, -) -> &'a NcPlane { +) -> NcResult<&'a NcPlane> { unsafe { - let s = crate::notcurses_stdplane_const(nc); - crate::ncplane_dim_yx(s, &mut (*y as i32), &mut (*x as i32)); - &*s + let sp = crate::notcurses_stdplane_const(nc); + if sp != null() { + crate::ncplane_dim_yx(sp, &mut (*y as i32), &mut (*x as i32)); + return Ok(&*sp); + } } + Err(NcError::new(NCRESULT_ERR)) } /// Returns our current idea of the terminal dimensions in rows and cols. diff --git a/rust/src/plane/methods.rs b/rust/src/plane/methods.rs index 1459126a4..513ff8660 100644 --- a/rust/src/plane/methods.rs +++ b/rust/src/plane/methods.rs @@ -3,7 +3,7 @@ use core::ptr::{null, null_mut}; use crate::{ - cstring, error, error_ptr, rstring, NcAlign, NcAlphaBits, NcBoxMask, NcCell, NcChannel, + cstring, error, error_ref_mut, rstring, NcAlign, NcAlphaBits, NcBoxMask, NcCell, NcChannel, NcChannelPair, NcColor, NcDimension, NcEgc, NcFadeCb, NcOffset, NcPaletteIndex, NcPlane, NcPlaneOptions, NcResizeCb, NcResult, NcRgb, NcStyleMask, NcTime, Notcurses, }; @@ -80,9 +80,8 @@ impl NcPlane { x: NcOffset, rows: NcDimension, cols: NcDimension, - ) -> &'a mut NcPlane { - let options = NcPlaneOptions::new(y, x, rows, cols); - unsafe { &mut *crate::ncpile_create(nc, &options) } + ) -> NcResult<&'a mut NcPlane> { + Self::with_options(nc, NcPlaneOptions::new(y, x, rows, cols)) } /// New NcPlane, expects an [NcPlaneOptions] struct. @@ -90,8 +89,11 @@ impl NcPlane { /// The returned plane will be the top, bottom, and root of this new pile. /// /// *C style function: [ncpile_create()][crate::ncpile_create].* - pub fn with_options<'a>(nc: &mut Notcurses, options: NcPlaneOptions) -> &'a mut NcPlane { - unsafe { &mut *crate::ncpile_create(nc, &options) } + pub fn with_options<'a>( + nc: &mut Notcurses, + options: NcPlaneOptions, + ) -> NcResult<&'a mut NcPlane> { + error_ref_mut![unsafe { crate::ncpile_create(nc, &options) }] } /// New NcPlane, bound to another NcPlane. @@ -104,8 +106,7 @@ impl NcPlane { rows: NcDimension, cols: NcDimension, ) -> NcResult<&'a mut NcPlane> { - let options = NcPlaneOptions::new(y, x, rows, cols); - error_ptr![unsafe { crate::ncplane_create(bound_to, &options) }] + Self::with_options_bound(bound_to, NcPlaneOptions::new(y, x, rows, cols)) } /// New NcPlane, bound to another plane, expects an [NcPlaneOptions] struct. @@ -117,7 +118,7 @@ impl NcPlane { bound_to: &mut NcPlane, options: NcPlaneOptions, ) -> NcResult<&'a mut NcPlane> { - error_ptr![unsafe { crate::ncplane_create(bound_to, &options) }] + error_ref_mut![unsafe { crate::ncplane_create(bound_to, &options) }] } /// New NcPlane, with the same dimensions of the terminal. @@ -125,15 +126,13 @@ impl NcPlane { /// The returned plane will be the top, bottom, and root of this new pile. /// /// *(No equivalent C style function)* - pub fn new_termsize<'a>(nc: &mut Notcurses) -> &'a mut NcPlane { + pub fn new_termsize<'a>(nc: &mut Notcurses) -> NcResult<&'a mut NcPlane> { let (trows, tcols) = crate::notcurses_term_dim_yx(nc); assert![(trows > 0) & (tcols > 0)]; - unsafe { - &mut *crate::ncpile_create( - nc, - &NcPlaneOptions::new(0, 0, trows as NcDimension, tcols as NcDimension), - ) - } + Self::with_options( + nc, + NcPlaneOptions::new(0, 0, trows as NcDimension, tcols as NcDimension), + ) } /// Destroys this NcPlane. @@ -996,7 +995,7 @@ impl NcPlane { /// /// *C style function: [ncplane_notcurses()][crate::ncplane_notcurses].* pub fn notcurses<'a>(&mut self) -> NcResult<&'a mut Notcurses> { - error_ptr![unsafe { crate::ncplane_notcurses(self) }] + error_ref_mut![unsafe { crate::ncplane_notcurses(self) }] } /// Gets an immutable reference to the [Notcurses] context of this NcPlane. diff --git a/rust/src/widgets/menu/methods.rs b/rust/src/widgets/menu/methods/menu.rs similarity index 68% rename from rust/src/widgets/menu/methods.rs rename to rust/src/widgets/menu/methods/menu.rs index a2a28515f..167ad4d5a 100644 --- a/rust/src/widgets/menu/methods.rs +++ b/rust/src/widgets/menu/methods/menu.rs @@ -1,10 +1,8 @@ -//! `NcMenu*` methods and associated functions. - use core::ptr::null_mut; use crate::{ - cstring, error, error_ptr, error_str, ncmenu_create, NcChannelPair, NcInput, NcMenu, - NcMenuItem, NcMenuOptions, NcMenuSection, NcPlane, NcResult, + cstring, error, error_ref_mut, error_str, ncmenu_create, NcInput, NcMenu, NcMenuOptions, + NcPlane, NcResult, }; /// # `NcMenu` constructors & destructors @@ -12,8 +10,8 @@ impl NcMenu { /// New NcMenu. /// /// *C style function: [ncmenu_create()][crate::ncmenu_create].* - pub fn new<'a>(plane: &mut NcPlane) -> NcResult<&'a mut Self> { - Self::with_options(plane, NcMenuOptions::new()) + pub fn new_empty<'a>(plane: &mut NcPlane) -> NcResult<&'a mut Self> { + Self::new(plane, NcMenuOptions::new_empty()) } /// Creates an [NcMenu] with the specified options. @@ -23,8 +21,8 @@ impl NcMenu { /// [NcPlane]s kept atop other NcPlanes. /// /// *C style function: [ncmenu_create()][crate::ncmenu_create].* - pub fn with_options<'a>(plane: &mut NcPlane, options: NcMenuOptions) -> NcResult<&'a mut Self> { - error_ptr![unsafe { ncmenu_create(plane, &options) }, "Creating NcMenu"] + pub fn new<'a>(plane: &mut NcPlane, options: NcMenuOptions) -> NcResult<&'a mut Self> { + error_ref_mut![unsafe { ncmenu_create(plane, &options) }, "Creating NcMenu"] } /// Destroys an NcMenu created with [create()][NcMenu#method.create]. @@ -37,7 +35,7 @@ impl NcMenu { /// # `NcMenu` methods impl NcMenu { - /// Disables or enables an [NcMenuItem]. + /// Disables or enables an [NcMenuItem][crate::NcMenuItem]. /// /// *C style function: [ncmenu_item_set_status()][crate::ncmenu_item_set_status].* pub fn ncmenu_item_set_status( @@ -51,9 +49,10 @@ impl NcMenu { }] } - /// Returns the [NcMenuItem] description corresponding to the mouse click `click`. + /// Returns the [NcMenuItem][crate::NcMenuItem] description + /// corresponding to the mouse `click`. /// - /// The [NcMenuItem] must be on an actively unrolled section, and the click + /// The NcMenuItem must be on an actively unrolled section, and the click /// must be in the area of a valid item. /// /// If `ninput` is provided, and the selected item has a shortcut, @@ -118,7 +117,7 @@ impl NcMenu { /// /// *C style function: [ncmenu_plane()][crate::ncmenu_plane].* pub fn ncmenu_plane(&mut self) -> NcResult<&NcPlane> { - error_ptr![ + error_ref_mut![ unsafe { crate::ncmenu_plane(self) }, "Getting the backing NcPlane" ] @@ -142,7 +141,7 @@ impl NcMenu { error![unsafe { crate::ncmenu_prevsection(self) }] } - /// Rolls up any unrolled [NcMenuSection], + /// Rolls up any unrolled [NcMenuSection][crate::NcMenuSection], /// and hides this NcMenu if using hiding. /// /// *C style function: [ncmenu_rollup()][crate::ncmenu_rollup].* @@ -170,79 +169,12 @@ impl NcMenu { ] } - /// Unrolls the specified [NcMenuSection], making the menu visible if it was - /// invisible, and rolling up any NcMenuSection that is already unrolled. + /// Unrolls the specified [NcMenuSection][crate::NcMenuSection], + /// making the menu visible if it was invisible, + /// and rolling up any NcMenuSection that is already unrolled. /// /// *C style function: [ncmenu_unroll()][crate::ncmenu_unroll].* pub fn ncmenu_unroll(&mut self, sectionindex: u32) -> NcResult<()> { error![unsafe { crate::ncmenu_unroll(self, sectionindex as i32) }] } } - -/// # `NcMenuOptions` Constructors -impl NcMenuOptions { - /// New NcMenuOptions. - pub fn new() -> Self { - Self::with_options(&mut [], 0, 0, 0, 0) - } - - /// New NcMenuOptions with width options. - pub fn with_options( - sections: &mut [NcMenuSection], - count: u32, - headerc: NcChannelPair, - sectionc: NcChannelPair, - flags: u64, - ) -> Self { - Self { - // array of 'sectioncount' `MenuSection`s - sections: sections as *mut _ as *mut NcMenuSection, /// XXX TEST - - // must be positive TODO - sectioncount: count as i32, - - // styling for header - headerchannels: headerc, - - // styling for sections - sectionchannels: sectionc, - - // flag word of NCMENU_OPTION_* - flags: flags, - } - } -} - -/// # `NcMenuItem` Constructors -impl NcMenuItem { - /// New NcMenuItem. - pub fn new(mut desc: i8, shortcut: NcInput) -> Self { - Self { - // utf-8 menu item, NULL for horizontal separator - desc: &mut desc, - - // ´NcInput´ shortcut, all should be distinct - shortcut, - } - } -} - -/// # `NcMenuSection` Constructors -impl NcMenuSection { - /// New NcMenuSection. - pub fn new(name: &str, itemcount: i32, items: &mut [NcMenuItem], shortcut: NcInput) -> Self { - Self { - // utf-8 name string - name: cstring![name] as *mut i8, - - // - itemcount, - - // array of itemcount `NcMenuItem`s - items: items as *mut _ as *mut NcMenuItem, - - // shortcut, will be underlined if present in name - shortcut, - } - } -} diff --git a/rust/src/widgets/menu/methods/mod.rs b/rust/src/widgets/menu/methods/mod.rs new file mode 100644 index 000000000..721c4600c --- /dev/null +++ b/rust/src/widgets/menu/methods/mod.rs @@ -0,0 +1,53 @@ +//! `NcMenu*` methods and associated functions. + +use core::ptr::null_mut; + +use crate::{cstring, cstring_mut, NcInput, NcMenuItem, NcMenuSection}; + +mod menu; +mod options; + +pub use menu::*; +pub use options::*; + +/// # `NcMenuItem` Constructors +impl NcMenuItem { + /// New NcMenuItem. + pub fn new(desc: &str, shortcut: NcInput) -> Self { + Self { + // utf-8 menu item, NULL for horizontal separator + desc: cstring_mut![desc], + + // ´NcInput´ shortcut, all should be distinct + shortcut, + } + } + + /// New empty NcMenuItem. + pub fn new_empty() -> Self { + Self { + desc: null_mut(), + shortcut: NcInput::new_empty(), + } + } +} + +/// # `NcMenuSection` Constructors +impl NcMenuSection { + /// New NcMenuSection. + pub fn new(name: &str, mut items: Vec, shortcut: NcInput) -> Self { + Self { + // utf-8 name string + name: cstring![name] as *mut i8, + + // + itemcount: items.len() as i32, + + // array of itemcount `NcMenuItem`s + items: items.as_mut_ptr() as *mut NcMenuItem, + + // shortcut, will be underlined if present in name + shortcut, + } + } +} diff --git a/rust/src/widgets/menu/methods/options.rs b/rust/src/widgets/menu/methods/options.rs new file mode 100644 index 000000000..9239fc6f7 --- /dev/null +++ b/rust/src/widgets/menu/methods/options.rs @@ -0,0 +1,70 @@ +use crate::{NcChannelPair, NcMenuOptions, NcMenuSection}; + +/// # `NcMenuOptions` constructors +impl NcMenuOptions { + /// New NcMenuOptions. + pub fn new(sections: Vec) -> Self { + Self::with_all_args(sections, 0, 0, 0) + } + + /// New empty NcMenuOptions. + pub fn new_empty() -> Self { + Self::with_all_args(vec![], 0, 0, 0) + } + + /// New NcMenuOptions with width options. + pub fn with_all_args( + mut sections: Vec, + headerc: NcChannelPair, + sectionc: NcChannelPair, + flags: u64, + ) -> Self { + Self { + // array of 'sectioncount' `MenuSection`s + sections: sections.as_mut_ptr() as *mut NcMenuSection, + + // + sectioncount: sections.len() as i32, + + // styling for header + headerchannels: headerc, + + // styling for sections + sectionchannels: sectionc, + + // flag word of NCMENU_OPTION_* + flags: flags, + } + } +} + +/// # `NcMenuOptions` methods +impl NcMenuOptions { + /// Returns the styling for the header. + /// + /// *(No equivalent C style function)* + pub const fn header_channels(&self) -> NcChannelPair { + self.headerchannels + } + + /// Returns a mutable reference of the styling for the sections. + /// + /// *(No equivalent C style function)* + pub fn header_channels_mut<'a>(&'a mut self) -> &'a mut NcChannelPair { + &mut self.headerchannels + } + + /// Returns the styling for the sections. + /// + /// *(No equivalent C style function)* + pub const fn section_channels(&self) -> NcChannelPair { + self.sectionchannels + } + + /// Returns a mutable reference of the styling for the sections. + /// + /// *(No equivalent C style function)* + pub fn section_channels_mut<'a>(&'a mut self) -> &'a mut NcChannelPair { + &mut self.sectionchannels + } +} diff --git a/rust/src/widgets/menu/mod.rs b/rust/src/widgets/menu/mod.rs index 53a6418e2..19eebc538 100644 --- a/rust/src/widgets/menu/mod.rs +++ b/rust/src/widgets/menu/mod.rs @@ -32,9 +32,12 @@ mod methods; /// Either no sections are visible, and the menu is rolled up, or exactly one /// section is unrolled. /// -/// `ncmenu_rollup` places an `NcMenu` in the rolled up state. -/// `ncmenu_unroll` rolls up any unrolled section and unrolls the specified one. -/// `ncmenu_destroy` removes a menu bar, and frees all associated resources. +/// - [rollup()][NcMenu#method.rollup] +/// places an `NcMenu` in the rolled up state. +/// - [unroll()][NcMenu#method.] +/// rolls up any unrolled section and unrolls the specified one. +/// - [destroy()][NcMenu#method.destroy] +/// removes a menu bar, and frees all associated resources. /// /// `type in C: ncmenu (struct)` pub type NcMenu = crate::bindings::ffi::ncmenu; diff --git a/rust/src/widgets/reader/methods.rs b/rust/src/widgets/reader/methods.rs index aaa4096a6..6b53375fb 100644 --- a/rust/src/widgets/reader/methods.rs +++ b/rust/src/widgets/reader/methods.rs @@ -1,6 +1,6 @@ //! `NcReader*` methods and associated functions. -use crate::{error_ptr, ncreader_create, NcPlane, NcReader, NcReaderOptions, NcResult}; +use crate::{error_ref_mut, ncreader_create, NcPlane, NcReader, NcReaderOptions, NcResult}; /// # `NcReaderOptions` Constructors impl NcReaderOptions { @@ -29,6 +29,6 @@ impl NcReader { plane: &mut NcPlane, options: NcReaderOptions, ) -> NcResult<&'a mut Self> { - error_ptr![unsafe { ncreader_create(plane, &options) }] + error_ref_mut![unsafe { ncreader_create(plane, &options) }] } }