use std::{ptr, fmt, convert::TryInto, hash::{Hash, Hasher}};
use ncursesw::{panels, SCREEN, panels::PANEL};
use crate::{Screen, Origin, Window, NCurseswWinError, gen::HasHandle, panels::funcs};
pub struct Panel {
screen: Option<SCREEN>,
handle: PANEL,
free_on_drop: bool
}
impl HasHandle<PANEL> for Panel {
fn _from(screen: Option<SCREEN>, handle: PANEL, free_on_drop: bool) -> Self {
assert!(screen.map_or_else(|| true, |screen| !screen.is_null()), "Panel::_from() : screen.is_null()");
assert!(!handle.is_null(), "Panel::_from() : handle.is_null()");
Self { screen, handle, free_on_drop }
}
fn _screen(&self) -> Option<SCREEN> {
self.screen
}
fn _handle(&self) -> PANEL {
self.handle
}
}
impl Panel {
pub fn new(window: &Window) -> result!(Self) {
Ok(Self::_from(window._screen(), panels::new_panel(window._handle())?, true))
}
#[deprecated(since = "0.3.1", note = "Use Panel::new() instead")]
pub fn new_panel(window: &Window) -> result!(Self) {
Self::new(window)
}
pub fn screen(&self) -> Option<Screen> {
self.screen.map(|screen| Screen::_from(screen, false))
}
pub fn bottom_panel(&self) -> result!(()) {
Ok(panels::bottom_panel(self.handle)?)
}
pub fn top_panel(&self) -> result!(()) {
Ok(panels::top_panel(self.handle)?)
}
pub fn show_panel(&self) -> result!(()) {
Ok(panels::show_panel(self.handle)?)
}
pub fn hide_panel(&self) -> result!(()) {
Ok(panels::hide_panel(self.handle)?)
}
pub fn panel_window(&self) -> result!(Window) {
Ok(Window::_from(self.screen, panels::panel_window(self.handle)?, false))
}
pub fn replace_panel(&self, window: &Window) -> result!(()) {
assert!(self.screen == window._screen());
Ok(panels::replace_panel(self.handle, window._handle())?)
}
pub fn move_panel(&self, origin: Origin) -> result!(()) {
Ok(panels::move_panel(self.handle, origin.try_into()?)?)
}
pub fn panel_hidden(&self) -> result!(bool) {
Ok(panels::panel_hidden(self.handle)?)
}
pub fn panel_above(&self) -> result!(Self) {
funcs::panel_above(Some(self))
}
pub fn panel_below(&self) -> result!(Self) {
funcs::panel_below(Some(self))
}
pub fn set_panel_userptr<T>(&self, ptr: Option<Box<&T>>) -> result!(()) {
Ok(panels::set_panel_userptr(self.handle, ptr.map(|ptr| Box::into_raw(ptr) as *const libc::c_void))?)
}
pub fn panel_userptr<T>(&self) -> Option<Box<T>> {
panels::panel_userptr(self.handle).map(|ptr| unsafe { Box::from_raw(ptr as *mut T) })
}
}
impl Drop for Panel {
fn drop(&mut self) {
if self.free_on_drop {
if let Err(source) = panels::del_panel(self.handle) {
panic!("{} @ ({:p})", source, self.handle)
}
}
}
}
unsafe impl Send for Panel { } unsafe impl Sync for Panel { }
impl PartialEq for Panel {
fn eq(&self, rhs: &Self) -> bool {
self.screen == rhs.screen && ptr::eq(self.handle, rhs.handle)
}
}
impl Eq for Panel { }
impl Hash for Panel {
fn hash<H: Hasher>(&self, state: &mut H) {
self.handle.hash(state);
}
}
impl AsRef<Panel> for Panel {
fn as_ref(&self) -> &Self {
self
}
}
impl Clone for Panel {
fn clone(&self) -> Self {
Self::_from(self.screen.clone(), self.handle.clone(), false)
}
}
impl fmt::Debug for Panel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Panel {{ screen: {:?}, handle: {:p}, free_on_drop: {} }}", self.screen, self.handle, self.free_on_drop)
}
}