use std::{ptr, fmt, convert::TryFrom, hash::{Hash, Hasher}};
use ncursesw::{menu, menu::ITEM, menu::ItemOptions};
use crate::NCurseswWinError;
pub struct MenuItem {
handle: ITEM, free_on_drop: bool
}
impl MenuItem {
pub(in crate::menu) fn _from(handle: ITEM, free_on_drop: bool) -> Self {
assert!(!handle.is_null(), "MenuItem::_from() : handle.is_null()");
Self { handle, free_on_drop }
}
pub(in crate::menu) fn _handle(&self) -> ITEM {
self.handle
}
}
impl MenuItem {
pub fn new<S: Into<String>>(name: S, description: S) -> result!(Self) {
let name = name.into().to_string();
let description = description.into().to_string();
Ok(Self::_from(menu::new_item(name.as_str(), description.as_str())?, true))
}
#[deprecated(since = "0.4.0", note = "Use MenuItem::new() instead")]
pub fn new_item<S: Into<String>>(name: S, description: S) -> result!(Self) {
Self::new(name, description)
}
pub fn item_description(&self) -> result!(String) {
Ok(menu::item_description(self.handle)?)
}
pub fn item_index(&self) -> result!(usize) {
Ok(usize::try_from(menu::item_index(self.handle)?)?)
}
pub fn item_name(&self) -> result!(String) {
Ok(menu::item_name(self.handle)?)
}
pub fn item_opts(&self) -> ItemOptions {
menu::item_opts(Some(self.handle))
}
pub fn item_opts_off(&self, opts: ItemOptions) -> result!(()) {
Ok(menu::item_opts_off(Some(self.handle), opts)?)
}
pub fn item_opts_on(&self, opts: ItemOptions) -> result!(()) {
Ok(menu::item_opts_on(Some(self.handle), opts)?)
}
pub fn item_userptr<T>(&self) -> Option<Box<T>> {
menu::item_userptr(Some(self.handle)).as_mut().map(|userptr| unsafe { Box::from_raw(*userptr as *mut T) })
}
pub fn item_value(&self) -> bool {
menu::item_value(self.handle)
}
pub fn item_visible(&self) -> bool {
menu::item_visible(self.handle)
}
pub fn set_item_opts(&self, opts: ItemOptions) -> result!(()) {
Ok(menu::set_item_opts(Some(self.handle), opts)?)
}
pub fn set_item_userptr<T>(&self, userptr: Option<Box<&T>>) {
menu::set_item_userptr(Some(self.handle), userptr.map(|userptr| Box::into_raw(userptr) as *mut libc::c_void))
}
pub fn set_item_value(&self, value: bool) -> result!(()) {
Ok(menu::set_item_value(self.handle, value)?)
}
}
impl Drop for MenuItem {
fn drop(&mut self) {
if self.free_on_drop {
if let Err(source) = menu::free_item(self.handle) {
panic!("{} @ {:?}", source, self)
}
}
}
}
unsafe impl Send for MenuItem { } unsafe impl Sync for MenuItem { }
impl PartialEq for MenuItem {
fn eq(&self, rhs: &Self) -> bool {
ptr::eq(self.handle, rhs.handle)
}
}
impl Eq for MenuItem { }
impl Hash for MenuItem {
fn hash<H: Hasher>(&self, state: &mut H) {
self.handle.hash(state);
}
}
impl AsRef<MenuItem> for MenuItem {
fn as_ref(&self) -> &Self {
self
}
}
impl Clone for MenuItem {
fn clone(&self) -> Self {
Self::_from(self.handle.clone(), false)
}
}
impl fmt::Debug for MenuItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "MenuItem {{ handle: {:p}, free_on_drop: {} }}", self.handle, self.free_on_drop)
}
}