use crate::image::Image;
pub use crate::prelude::*;
use fltk_sys::menu::*;
use std::{
ffi::{CStr, CString},
mem,
os::raw,
};
#[derive(WidgetExt, MenuExt, Debug)]
pub struct MenuBar {
_inner: *mut Fl_Menu_Bar,
}
#[derive(WidgetExt, MenuExt, Debug)]
pub struct MenuButton {
_inner: *mut Fl_Menu_Button,
}
#[derive(WidgetExt, MenuExt, Debug)]
pub struct Choice {
_inner: *mut Fl_Choice,
}
#[derive(Debug, Clone)]
pub struct MenuItem {
_inner: *mut Fl_Menu_Item,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum MenuFlag {
Normal = 0,
Inactive = 1,
Toggle = 2,
Value = 4,
Radio = 8,
Invisible = 0x10,
SubmenuPointer = 0x20,
Submenu = 0x40,
MenuDivider = 0x80,
MenuHorizontal = 0x100,
}
impl MenuItem {
pub fn new(choices: Vec<&str>) -> MenuItem {
unsafe {
let sz = choices.len();
let mut temp: Vec<*mut raw::c_char> = vec![];
for choice in choices {
temp.push(CString::new(choice).unwrap().into_raw() as *mut raw::c_char);
}
let item_ptr = Fl_Menu_Item_new(temp.as_ptr() as *mut *mut raw::c_char, sz as i32);
assert!(!item_ptr.is_null());
MenuItem { _inner: item_ptr }
}
}
pub fn popup(&mut self, x: i32, y: i32) -> Option<MenuItem> {
unsafe {
let item = Fl_Menu_Item_popup(self._inner, x, y);
if item.is_null() {
None
} else {
let item = MenuItem {
_inner: item as *mut Fl_Menu_Item,
};
Some(item)
}
}
}
pub fn label(&self) -> String {
unsafe {
let label_ptr = Fl_Menu_Item_label(self._inner);
assert!(!label_ptr.is_null(), "Failed to get menu item label!");
CStr::from_ptr(label_ptr as *mut raw::c_char)
.to_string_lossy()
.to_string()
}
}
pub fn set_label(&mut self, txt: &str) {
unsafe {
let txt = CString::new(txt).unwrap();
Fl_Menu_Item_set_label(self._inner, txt.into_raw() as *const raw::c_char);
}
}
pub fn label_type<T: WidgetType>(&self) -> T {
unsafe { T::from_i32(Fl_Menu_Item_label_type(self._inner)) }
}
pub fn set_label_type<T: WidgetType>(&mut self, typ: T) {
unsafe {
Fl_Menu_Item_set_label_type(self._inner, typ.to_int());
}
}
pub fn label_color(&self) -> Color {
unsafe { mem::transmute(Fl_Menu_Item_label_color(self._inner)) }
}
pub fn set_label_color(&mut self, color: Color) {
unsafe { Fl_Menu_Item_set_label_color(self._inner, color as u32) }
}
pub fn label_font(&self) -> Font {
unsafe { mem::transmute(Fl_Menu_Item_label_font(self._inner)) }
}
pub fn set_label_font(&mut self, font: Font) {
unsafe { Fl_Menu_Item_set_label_font(self._inner, font as i32) }
}
pub fn label_size(&self) -> u32 {
unsafe { Fl_Menu_Item_label_size(self._inner) as u32 }
}
pub fn set_label_size(&mut self, sz: u32) {
unsafe { Fl_Menu_Item_set_label_size(self._inner, sz as i32) }
}
pub fn value(&self) -> bool {
unsafe {
match Fl_Menu_Item_value(self._inner) {
0 => false,
_ => true,
}
}
}
pub fn set(&mut self) {
unsafe { Fl_Menu_Item_set(self._inner) }
}
pub fn clear(&mut self) {
unsafe { Fl_Menu_Item_clear(self._inner) }
}
pub fn visible(&self) -> bool {
unsafe {
match Fl_Menu_Item_visible(self._inner) {
0 => false,
_ => true,
}
}
}
pub fn active(&mut self) -> bool {
unsafe {
match Fl_Menu_Item_active(self._inner) {
0 => false,
_ => true,
}
}
}
pub fn activate(&mut self) {
unsafe { Fl_Menu_Item_activate(self._inner) }
}
pub fn deactivate(&mut self) {
unsafe { Fl_Menu_Item_deactivate(self._inner) }
}
pub fn show(&mut self) {
unsafe { Fl_Menu_Item_show(self._inner) }
}
pub fn hide(&mut self) {
unsafe { Fl_Menu_Item_hide(self._inner) }
}
}
#[cfg(test)]
mod menu {
use super::*;
#[test]
fn label() {
let mut menu = MenuBar::new(0, 0, 0, 0, "hello");
menu.set_label("cloned");
}
#[test]
fn tooltip() {
let mut menu = MenuBar::new(0, 0, 0, 0, "hello");
menu.set_tooltip("tooltip");
assert!(menu.tooltip().unwrap() == "tooltip");
}
}