use crate::{
platform::{MenuApi, MenuItemApi, Wrapper},
platform_impl::{MenuImpl, MenuItemImpl},
ContextOwner,
Icon,
};
#[derive(Debug)]
pub enum Action {
Event(String),
Callback(fn()),
}
impl Action {
pub fn new_event<S>(name: S) -> Self
where
S: Into<String>,
{
Self::Event(name.into())
}
pub fn new_callback(callback: fn()) -> Self { Self::Callback(callback) }
}
#[derive(Debug, Default)]
pub struct ShortCode {
pub(crate) macos: Option<String>,
}
impl ShortCode {
pub fn macos_code(&self) -> Option<&String> { self.macos.as_ref() }
}
#[derive(Debug)]
pub struct MenuItem(MenuItemImpl);
impl MenuItem {
pub fn builder() -> MenuItemBuilder { MenuItemBuilder::new() }
fn new(ctx: &impl ContextOwner) -> Self { Self(MenuItemImpl::new(ctx, false)) }
pub fn separator(ctx: &impl ContextOwner) -> Self { Self(MenuItemImpl::new(ctx, true)) }
}
impl MenuItem {
pub fn set_title<S>(&mut self, title: S)
where
S: Into<String>,
{
self.0.set_title(title.into());
}
pub fn title(&self) -> String { self.0.title() }
pub fn set_action(&mut self, action: Option<Action>) { self.0.set_action(action); }
pub fn set_submenu(&mut self, submenu: Option<Menu>) { self.0.set_submenu(submenu); }
pub fn submenu(&self) -> Option<&Menu> { self.0.submenu() }
pub fn submenu_mut(&mut self) -> Option<&mut Menu> { self.0.submenu_mut() }
pub fn has_submenu(&self) -> bool { self.0.has_submenu() }
pub fn set_short_code(&mut self, short_code: ShortCode) { self.0.set_short_code(short_code); }
pub fn short_code(&self) -> &ShortCode { self.0.short_code() }
pub fn set_enabled(&mut self, enabled: bool) { self.0.set_enabled(enabled); }
pub fn enabled(&self) -> bool { self.0.enabled() }
pub fn set_tooltip(&mut self, tooltip: Option<String>) { self.0.set_tooltip(tooltip); }
pub fn tooltip(&self) -> Option<String> { self.0.tooltip() }
pub fn set_icon(&mut self, icon: Option<Icon>) { self.0.set_icon(icon); }
pub fn icon(&self) -> Option<&Icon> { self.0.icon() }
}
impl Wrapper<MenuItemImpl> for MenuItem {
#[inline]
fn get_impl(&self) -> &MenuItemImpl { &self.0 }
#[inline]
fn get_impl_mut(&mut self) -> &mut MenuItemImpl { &mut self.0 }
}
#[derive(Debug, Default)]
pub struct MenuItemBuilder {
title: Option<String>,
action: Option<Action>,
submenu: Option<Menu>,
short_code: ShortCode,
enabled: Option<bool>,
icon: Option<Icon>,
}
impl MenuItemBuilder {
fn new() -> Self {
Self {
..Default::default()
}
}
pub fn with_title<S>(mut self, title: S) -> MenuItemBuilder
where
S: Into<String>,
{
self.title = Some(title.into());
self
}
pub fn with_action(mut self, action: Action) -> MenuItemBuilder {
self.action = Some(action);
self
}
pub fn with_submenu(mut self, submenu: Menu) -> MenuItemBuilder {
self.submenu = Some(submenu);
self
}
pub fn with_macos_short_code<S>(mut self, short_code: S) -> MenuItemBuilder
where
S: Into<String>,
{
self.short_code.macos = Some(short_code.into());
self
}
pub fn with_enabled(mut self, enabled: bool) -> MenuItemBuilder {
self.enabled = Some(enabled);
self
}
pub fn with_icon(mut self, icon: Icon) -> MenuItemBuilder {
self.icon = Some(icon);
self
}
pub fn build(self, ctx: &impl ContextOwner) -> MenuItem {
let mut item = MenuItem::new(ctx);
if let Some(title) = self.title {
item.set_title(title);
}
if self.action.is_some() {
item.set_action(self.action);
}
if self.submenu.is_some() {
item.set_submenu(self.submenu);
}
item.set_short_code(self.short_code);
if let Some(enabled) = self.enabled {
item.set_enabled(enabled);
}
if self.icon.is_some() {
item.set_icon(self.icon);
}
item
}
}
#[derive(Debug)]
pub struct Menu(MenuImpl);
impl Menu {
pub fn builder() -> MenuBuilder { MenuBuilder::new() }
fn new(ctx: &impl ContextOwner, items: Vec<MenuItem>) -> Self {
Self(MenuImpl::new(ctx, items))
}
}
impl Wrapper<MenuImpl> for Menu {
#[inline]
fn get_impl(&self) -> &MenuImpl { &self.0 }
#[inline]
fn get_impl_mut(&mut self) -> &mut MenuImpl { &mut self.0 }
}
#[derive(Debug)]
pub struct MenuBuilder {
items: Vec<MenuItem>,
}
impl MenuBuilder {
#[inline]
fn new() -> Self {
Self {
items: Vec::new()
}
}
pub fn with_item(mut self, item: MenuItem) -> MenuBuilder {
self.items.push(item);
self
}
pub fn build(self, ctx: &impl ContextOwner) -> Menu { Menu::new(ctx, self.items) }
}