use crate::id::Id;
use crate::menus::{Menu, MenuItem};
#[cfg(feature = "xrc")]
use crate::window::WindowHandle;
#[cfg(feature = "xrc")]
use crate::xrc::XmlResource;
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use wxdragon_sys as ffi;
pub struct MenuBar {
ptr: *mut ffi::wxd_MenuBar_t,
}
impl MenuBar {
pub fn builder() -> MenuBarBuilder {
MenuBarBuilder::new()
}
pub(crate) unsafe fn from_ptr(ptr: *mut ffi::wxd_MenuBar_t) -> Self {
Self { ptr }
}
#[cfg(feature = "xrc")]
pub fn get_item_by_name(&self, parent_handle: WindowHandle, item_name: &str) -> Option<MenuItem> {
MenuItem::from_xrc_name(parent_handle, item_name)
}
#[cfg(feature = "xrc")]
pub fn from_xrc_name(menubar_name: &str) -> Option<Self> {
let xml_resource = XmlResource::get();
let name_c = CString::new(menubar_name).unwrap_or_default();
let ptr = unsafe {
ffi::wxd_XmlResource_LoadMenuBar(
xml_resource.as_ptr(),
std::ptr::null_mut(), name_c.as_ptr(),
)
};
if ptr.is_null() {
None
} else {
Some(unsafe { MenuBar::from_ptr(ptr) })
}
}
pub(crate) unsafe fn as_ptr(&self) -> *mut ffi::wxd_MenuBar_t {
self.ptr
}
pub fn enable_item(&self, id: Id, enable: bool) -> bool {
unsafe { ffi::wxd_MenuBar_EnableItem(self.ptr, id, enable) }
}
pub fn is_item_enabled(&self, id: Id) -> bool {
unsafe { ffi::wxd_MenuBar_IsItemEnabled(self.ptr, id) }
}
pub fn check_item(&self, id: Id, check: bool) {
unsafe { ffi::wxd_MenuBar_CheckItem(self.ptr, id, check) }
}
pub fn is_item_checked(&self, id: Id) -> bool {
unsafe { ffi::wxd_MenuBar_IsItemChecked(self.ptr, id) }
}
pub fn find_item(&self, id: Id) -> Option<MenuItem> {
let item_ptr = unsafe { ffi::wxd_MenuBar_FindItem(self.ptr, id, std::ptr::null_mut()) };
if item_ptr.is_null() {
None
} else {
Some(MenuItem::from_ptr(item_ptr))
}
}
pub fn find_item_and_menu(&self, id: Id) -> Option<(MenuItem, Menu)> {
let mut menu_ptr: *mut ffi::wxd_Menu_t = std::ptr::null_mut();
let item_ptr = unsafe { ffi::wxd_MenuBar_FindItem(self.ptr, id, &mut menu_ptr) };
if item_ptr.is_null() || menu_ptr.is_null() {
None
} else {
Some((MenuItem::from_ptr(item_ptr), Menu::from(menu_ptr as *const ffi::wxd_Menu_t)))
}
}
pub fn get_menu(&self, index: usize) -> Option<Menu> {
let ptr = unsafe { ffi::wxd_MenuBar_GetMenu(self.ptr, index) };
if ptr.is_null() {
None
} else {
Some(Menu::from(ptr as *const ffi::wxd_Menu_t))
}
}
pub fn get_menu_count(&self) -> usize {
unsafe { ffi::wxd_MenuBar_GetMenuCount(self.ptr) }
}
pub fn find_menu(&self, title: &str) -> i32 {
let c_title = CString::new(title).unwrap_or_default();
unsafe { ffi::wxd_MenuBar_FindMenu(self.ptr, c_title.as_ptr()) }
}
pub fn enable_top(&self, pos: usize, enable: bool) {
unsafe { ffi::wxd_MenuBar_EnableTop(self.ptr, pos, enable) }
}
pub fn get_menu_label(&self, pos: usize) -> String {
let len = unsafe { ffi::wxd_MenuBar_GetMenuLabel(self.ptr, pos, std::ptr::null_mut(), 0) };
if len <= 0 {
return String::new();
}
let mut buffer = vec![0u8; len as usize + 1];
unsafe { ffi::wxd_MenuBar_GetMenuLabel(self.ptr, pos, buffer.as_mut_ptr() as *mut _, buffer.len()) };
unsafe { CStr::from_ptr(buffer.as_ptr() as *const _).to_string_lossy().into_owned() }
}
pub fn set_menu_label(&self, pos: usize, label: &str) {
let c_label = CString::new(label).unwrap_or_default();
unsafe { ffi::wxd_MenuBar_SetMenuLabel(self.ptr, pos, c_label.as_ptr()) }
}
pub fn replace(&self, pos: usize, menu: Menu, title: &str) -> Option<Menu> {
let c_title = CString::new(title).unwrap_or_default();
let ptr = unsafe { ffi::wxd_MenuBar_Replace(self.ptr, pos, menu.into_raw_mut(), c_title.as_ptr()) };
if ptr.is_null() {
None
} else {
Some(Menu::from(ptr))
}
}
}
#[derive(Default)]
pub struct MenuBarBuilder {
style: i64,
items: Vec<(Menu, String)>, _marker: PhantomData<()>, }
impl MenuBarBuilder {
pub fn new() -> Self {
Default::default() }
pub fn with_style(mut self, style: i64) -> Self {
self.style = style;
self
}
pub fn append(mut self, menu: Menu, title: &str) -> Self {
self.items.push((menu, title.to_string()));
self
}
pub fn build(self) -> MenuBar {
let ptr = unsafe { ffi::wxd_MenuBar_Create(self.style as ffi::wxd_Style_t) };
if ptr.is_null() {
panic!("Failed to create MenuBar");
}
let menubar = MenuBar { ptr };
for (menu, title) in self.items {
let title_c = CString::new(title).unwrap_or_default();
unsafe { ffi::wxd_MenuBar_Append(menubar.ptr, menu.into_raw_mut(), title_c.as_ptr()) };
}
menubar
}
}
#[cfg(feature = "xrc")]
impl crate::xrc::XrcSupport for MenuBar {
unsafe fn from_xrc_ptr(ptr: *mut wxdragon_sys::wxd_Window_t) -> Self {
let menubar_ptr = ptr as *mut wxdragon_sys::wxd_MenuBar_t;
Self { ptr: menubar_ptr }
}
}
impl crate::window::WxWidget for MenuBar {
fn handle_ptr(&self) -> *mut wxdragon_sys::wxd_Window_t {
self.ptr as *mut wxdragon_sys::wxd_Window_t
}
fn get_id(&self) -> i32 {
-1 }
}
impl crate::event::WxEvtHandler for MenuBar {
unsafe fn get_event_handler_ptr(&self) -> *mut ffi::wxd_EvtHandler_t {
self.ptr as *mut ffi::wxd_EvtHandler_t
}
}
impl crate::event::MenuEvents for MenuBar {}