From 3099f3610003f513a386125d3cb81bfbf0ffe887 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 19 Jul 2021 20:59:09 +0700 Subject: Implement `Menu::map` naively --- core/src/menu.rs | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'core') diff --git a/core/src/menu.rs b/core/src/menu.rs index 52186140..e9d3d13a 100644 --- a/core/src/menu.rs +++ b/core/src/menu.rs @@ -26,15 +26,30 @@ impl Menu { Self { entries } } + /// Returns a [`MenuEntry`] iterator. + pub fn iter(&self) -> impl Iterator> { + self.entries.iter() + } + /// Adds an [`Entry`] to the [`Menu`]. pub fn push(mut self, entry: Entry) -> Self { self.entries.push(entry); self } - /// Returns a [`MenuEntry`] iterator. - pub fn iter(&self) -> impl Iterator> { - self.entries.iter() + /// Maps the `Message` of the [`Menu`] using the provided function. + /// + /// This is useful to compose menus and split them into different + /// abstraction levels. + pub fn map(self, f: &impl Fn(Message) -> B) -> Menu { + // TODO: Use a boxed trait to avoid reallocation of entries + Menu { + entries: self + .entries + .into_iter() + .map(|entry| entry.map(f)) + .collect(), + } } } @@ -71,7 +86,7 @@ impl Entry { let content = content.into(); let hotkey = hotkey.into(); - Entry::Item { + Self::Item { content, hotkey, on_activation, @@ -85,7 +100,26 @@ impl Entry { ) -> Self { let content = content.into(); - Entry::Dropdown { content, submenu } + Self::Dropdown { content, submenu } + } + + fn map(self, f: &impl Fn(Message) -> B) -> Entry { + match self { + Self::Item { + content, + hotkey, + on_activation, + } => Entry::Item { + content, + hotkey, + on_activation: f(on_activation), + }, + Self::Dropdown { content, submenu } => Entry::Dropdown { + content, + submenu: submenu.map(f), + }, + Self::Separator => Entry::Separator, + } } } -- cgit