use crate::bitmap::Bitmap;
use crate::event::{Event, EventType, WxEvtHandler};
use crate::menus::Menu;
use crate::window::{Window, WindowHandle, WxWidget};
use std::ffi::{CStr, CString};
use wxdragon_sys as ffi;
pub const ID_EXIT: i32 = ffi::WXD_ID_EXIT as i32;
pub const ID_ABOUT: i32 = ffi::WXD_ID_ABOUT as i32;
pub const ITEM_NORMAL: i32 = ffi::WXD_ITEM_NORMAL as i32;
pub const ITEM_CHECK: i32 = ffi::WXD_ITEM_CHECK as i32;
pub const ITEM_RADIO: i32 = ffi::WXD_ITEM_RADIO as i32;
pub const ITEM_SEPARATOR: i32 = ffi::WXD_ITEM_SEPARATOR as i32;
pub const ID_SEPARATOR: i32 = ffi::WXD_ITEM_SEPARATOR as i32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum ItemKind {
Normal = ffi::WXD_ITEM_NORMAL as i32,
Separator = ffi::WXD_ITEM_SEPARATOR as i32,
Check = ffi::WXD_ITEM_CHECK as i32,
Radio = ffi::WXD_ITEM_RADIO as i32,
}
impl From<ItemKind> for i32 {
fn from(kind: ItemKind) -> Self {
kind as i32
}
}
#[derive(Clone, Copy)]
pub struct MenuItem {
ptr: *mut ffi::wxd_MenuItem_t, parent_handle: WindowHandle,
item_id: i32,
}
impl From<*mut ffi::wxd_MenuItem_t> for MenuItem {
fn from(ptr: *mut ffi::wxd_MenuItem_t) -> Self {
MenuItem::from_ptr(ptr)
}
}
impl From<*const ffi::wxd_MenuItem_t> for MenuItem {
fn from(ptr: *const ffi::wxd_MenuItem_t) -> Self {
MenuItem::from_ptr(ptr as *mut ffi::wxd_MenuItem_t)
}
}
impl MenuItem {
pub(crate) fn from_ptr(ptr: *mut ffi::wxd_MenuItem_t) -> Self {
let owner_ptr = unsafe { ffi::wxd_MenuItem_GetOwningWindow(ptr) };
let item_id = unsafe { ffi::wxd_MenuItem_GetId(ptr) };
let parent_handle = WindowHandle::new(owner_ptr as *mut ffi::wxd_Window_t);
MenuItem {
ptr,
parent_handle,
item_id,
}
}
#[cfg(feature = "xrc")]
pub(crate) fn new(parent_handle: WindowHandle, item_id: i32) -> Self {
Self {
ptr: std::ptr::null_mut(), parent_handle,
item_id,
}
}
#[inline]
fn parent_ptr(&self) -> *mut ffi::wxd_Window_t {
self.parent_handle.get_ptr().unwrap_or(std::ptr::null_mut())
}
pub fn is_valid(&self) -> bool {
self.parent_handle.is_valid()
}
pub fn get_item_id(&self) -> i32 {
self.item_id
}
pub fn on_click<F>(&self, handler: F)
where
F: FnMut(Event) + 'static,
{
let ptr = self.parent_ptr();
if ptr.is_null() {
return;
}
let parent_window = unsafe { Window::from_ptr(ptr) };
parent_window.bind_with_id_internal(EventType::MENU, self.item_id, handler);
}
#[cfg(feature = "xrc")]
pub fn from_xrc_name(parent_handle: WindowHandle, item_name: &str) -> Option<Self> {
use crate::xrc::XmlResource;
let item_id = XmlResource::get_xrc_id(item_name);
if item_id != -1 {
Some(MenuItem::new(parent_handle, item_id))
} else {
None
}
}
pub fn set_label(&self, label: &str) {
if self.ptr.is_null() {
return;
}
let c_label = CString::new(label).unwrap_or_default();
unsafe {
ffi::wxd_MenuItem_SetLabel(self.ptr, c_label.as_ptr());
}
}
pub fn get_label(&self) -> String {
if self.ptr.is_null() {
return String::new();
}
let len = unsafe { ffi::wxd_MenuItem_GetLabel(self.ptr, std::ptr::null_mut(), 0) };
if len <= 0 {
return String::new();
}
let mut c_str = vec![0; len as usize + 1]; unsafe { ffi::wxd_MenuItem_GetLabel(self.ptr, c_str.as_mut_ptr(), c_str.len()) };
unsafe { CStr::from_ptr(c_str.as_ptr()).to_string_lossy().to_string() }
}
pub fn enable(&self, enable: bool) {
if self.ptr.is_null() {
return;
}
unsafe {
ffi::wxd_MenuItem_Enable(self.ptr, enable);
}
}
pub fn is_enabled(&self) -> bool {
if self.ptr.is_null() {
return true;
}
unsafe { ffi::wxd_MenuItem_IsEnabled(self.ptr) }
}
pub fn check(&self, check: bool) {
if self.ptr.is_null() {
return;
}
unsafe {
ffi::wxd_MenuItem_Check(self.ptr, check);
}
}
pub fn is_checked(&self) -> bool {
if self.ptr.is_null() {
return false;
}
unsafe { ffi::wxd_MenuItem_IsChecked(self.ptr) }
}
pub fn get_sub_menu(&self) -> Option<Menu> {
if self.ptr.is_null() {
return None;
}
let ptr = unsafe { ffi::wxd_MenuItem_GetSubMenu(self.ptr) };
if ptr.is_null() {
None
} else {
Some(Menu::from(ptr as *const ffi::wxd_Menu_t))
}
}
pub fn set_bitmap(&self, bitmap: &Bitmap) {
if self.ptr.is_null() {
return;
}
unsafe {
ffi::wxd_MenuItem_SetBitmap(self.ptr, bitmap.as_const_ptr());
}
}
pub fn get_bitmap(&self) -> Option<Bitmap> {
if self.ptr.is_null() {
return None;
}
let ptr = unsafe { ffi::wxd_MenuItem_GetBitmap(self.ptr) };
if ptr.is_null() {
None
} else {
Some(Bitmap::from(ptr))
}
}
pub fn as_const_ptr(&self) -> *const ffi::wxd_MenuItem_t {
self.ptr as *const _
}
pub unsafe fn destroy(&self) {
unsafe {
if !self.ptr.is_null() {
ffi::wxd_MenuItem_Destroy(self.ptr);
}
}
}
}
impl WxWidget for MenuItem {
fn handle_ptr(&self) -> *mut ffi::wxd_Window_t {
self.parent_handle.get_ptr().unwrap_or(std::ptr::null_mut())
}
fn get_id(&self) -> i32 {
self.item_id
}
}
impl WxEvtHandler for MenuItem {
unsafe fn get_event_handler_ptr(&self) -> *mut ffi::wxd_EvtHandler_t {
self.parent_handle.get_ptr().unwrap_or(std::ptr::null_mut()) as *mut ffi::wxd_EvtHandler_t
}
}