use azul_core::{
callbacks::{CoreCallback, CoreCallbackData},
dom::{Dom, EventFilter, HoverEventFilter, IdOrClass::Class, IdOrClassVec},
menu::{Menu, MenuItem, MenuItemVec, StringMenuItem},
refany::{OptionRefAny, RefAny},
};
pub const MENUBAR_CLASS: &str = "__azul-native-menubar";
pub const MENUBAR_ITEM_CLASS: &str = "azul-menubar-item";
const MENUBAR_CSS: &str = "display: flex; \
flex-direction: row; \
align-items: stretch; \
width: 100%; \
height: 26px; \
background: system:window-background; \
color: system:text; \
font-family: system:ui; \
font-size: 14px; \
padding-left: 2px;";
const MENUBAR_ITEM_CSS: &str = "display: flex; \
flex-direction: row; \
align-items: center; \
padding-left: 10px; \
padding-right: 10px; \
color: system:text; \
cursor: pointer; \
:hover { background: system:selection-background; color: system:selection-text; }";
#[must_use] pub fn build_menubar_dom(menu: &Menu) -> Dom {
let mut bar = Dom::create_div()
.with_ids_and_classes(IdOrClassVec::from_vec(vec![
Class(MENUBAR_CLASS.into()),
Class("azul-menubar".into()),
]))
.with_css(MENUBAR_CSS);
for item in menu.items.as_slice() {
if let MenuItem::String(s) = item {
bar = bar.with_child(build_menubar_item(s));
}
}
bar
}
fn build_menubar_item(item: &StringMenuItem) -> Dom {
let submenu = if item.children.as_slice().is_empty() {
Menu::create(MenuItemVec::from_vec(vec![MenuItem::String(item.clone())]))
} else {
Menu::create(item.children.clone())
};
Dom::create_div()
.with_ids_and_classes(IdOrClassVec::from_vec(vec![Class(MENUBAR_ITEM_CLASS.into())]))
.with_css(MENUBAR_ITEM_CSS)
.with_child(Dom::create_text(item.label.clone()))
.with_callbacks(
vec![CoreCallbackData {
event: EventFilter::Hover(HoverEventFilter::MouseUp),
callback: CoreCallback {
cb: callbacks::menubar_item_click as usize,
ctx: OptionRefAny::None,
},
refany: RefAny::new(submenu),
}]
.into(),
)
}
pub(crate) mod callbacks {
use azul_core::{callbacks::Update, menu::Menu, refany::RefAny};
use crate::callbacks::CallbackInfo;
pub(super) extern "C" fn menubar_item_click(mut data: RefAny, mut info: CallbackInfo) -> Update {
if let Some(menu) = data.downcast_ref::<Menu>() {
info.open_menu_for_hit_node(menu.clone());
}
Update::DoNothing
}
}