use crate::*; pub trait Command: Sized { fn run (&self, state: &mut S) -> Perhaps; } pub trait MatchInput: Sized { fn match_input (state: &S, input: &E::Input) -> Option; } pub struct MenuBar> { pub menus: Vec>, pub index: usize, } impl> MenuBar { pub fn new () -> Self { Self { menus: vec![], index: 0 } } pub fn add (mut self, menu: Menu) -> Self { self.menus.push(menu); self } } pub struct Menu> { pub title: String, pub items: Vec>, pub index: usize, } impl> Menu { pub fn new (title: impl AsRef) -> Self { Self { title: title.as_ref().to_string(), items: vec![], index: 0 } } pub fn add (mut self, item: MenuItem) -> Self { self.items.push(item); self } pub fn sep (mut self) -> Self { self.items.push(MenuItem::sep()); self } pub fn cmd (mut self, hotkey: &'static str, text: &'static str, command: C) -> Self { self.items.push(MenuItem::cmd(hotkey, text, command)); self } pub fn off (mut self, hotkey: &'static str, text: &'static str) -> Self { self.items.push(MenuItem::off(hotkey, text)); self } } pub enum MenuItem> { /// Unused. __(PhantomData, PhantomData), /// A separator. Skip it. Separator, /// A menu item with command, description and hotkey. Command(&'static str, &'static str, C), /// A menu item that can't be activated but has description and hotkey Disabled(&'static str, &'static str) } impl> MenuItem { pub fn sep () -> Self { Self::Separator } pub fn cmd (hotkey: &'static str, text: &'static str, command: C) -> Self { Self::Command(hotkey, text, command) } pub fn off (hotkey: &'static str, text: &'static str) -> Self { Self::Disabled(hotkey, text) } }