use std::borrow::Cow;
#[derive(Clone)]
pub enum MenuItem<'a, Message> {
Item {
label: Cow<'a, str>,
icon: Option<Cow<'a, str>>,
on_click: Message,
enabled: bool,
shortcut: Option<Cow<'a, str>>,
},
Separator,
Submenu {
label: Cow<'a, str>,
items: Vec<MenuItem<'a, Message>>,
},
}
impl<'a, Message> MenuItem<'a, Message> {
pub fn new(label: impl Into<Cow<'a, str>>, on_click: Message) -> Self {
Self::Item {
label: label.into(),
icon: None,
on_click,
enabled: true,
shortcut: None,
}
}
pub fn separator() -> Self {
Self::Separator
}
pub fn submenu(label: impl Into<Cow<'a, str>>, items: Vec<MenuItem<'a, Message>>) -> Self {
Self::Submenu {
label: label.into(),
items,
}
}
#[must_use]
pub fn icon(mut self, icon: impl Into<Cow<'a, str>>) -> Self {
if let Self::Item { icon: ref mut i, .. } = self {
*i = Some(icon.into());
}
self
}
#[must_use]
pub fn enabled(mut self, enabled: bool) -> Self {
if let Self::Item { enabled: ref mut e, .. } = self {
*e = enabled;
}
self
}
#[must_use]
pub fn shortcut(mut self, shortcut: impl Into<Cow<'a, str>>) -> Self {
if let Self::Item { shortcut: ref mut s, .. } = self {
*s = Some(shortcut.into());
}
self
}
}
pub struct Menu<'a, Message> {
pub items: Vec<MenuItem<'a, Message>>,
}
impl<'a, Message> Menu<'a, Message> {
#[must_use]
pub fn new() -> Self {
Self { items: Vec::new() }
}
#[must_use]
pub fn item(mut self, item: MenuItem<'a, Message>) -> Self {
self.items.push(item);
self
}
#[must_use]
pub fn push(mut self, label: impl Into<Cow<'a, str>>, on_click: Message) -> Self {
self.items.push(MenuItem::new(label, on_click));
self
}
#[must_use]
pub fn separator(mut self) -> Self {
self.items.push(MenuItem::Separator);
self
}
#[must_use]
pub fn submenu(mut self, label: impl Into<Cow<'a, str>>, items: Vec<MenuItem<'a, Message>>) -> Self {
self.items.push(MenuItem::submenu(label, items));
self
}
}
impl<'a, Message> Default for Menu<'a, Message> {
fn default() -> Self {
Self::new()
}
}
pub struct MenuBar<'a, Message> {
pub menus: Vec<(Cow<'a, str>, Menu<'a, Message>)>,
}
impl<'a, Message> MenuBar<'a, Message> {
#[must_use]
pub fn new() -> Self {
Self { menus: Vec::new() }
}
#[must_use]
pub fn menu(mut self, label: impl Into<Cow<'a, str>>, menu: Menu<'a, Message>) -> Self {
self.menus.push((label.into(), menu));
self
}
}
impl<'a, Message> Default for MenuBar<'a, Message> {
fn default() -> Self {
Self::new()
}
}