summaryrefslogtreecommitdiffstats
path: root/core/src/menu.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/menu.rs')
-rw-r--r--core/src/menu.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/core/src/menu.rs b/core/src/menu.rs
new file mode 100644
index 00000000..fe770216
--- /dev/null
+++ b/core/src/menu.rs
@@ -0,0 +1,84 @@
+//! Build menus for your application.
+use crate::keyboard::Hotkey;
+
+/// Menu representation.
+///
+/// This can be used by `shell` implementations to create a menu.
+#[derive(Debug, Clone, PartialEq)]
+pub struct Menu<Message> {
+ entries: Vec<Entry<Message>>,
+}
+
+impl<Message> Menu<Message> {
+ /// Creates an empty [`Menu`].
+ pub fn new() -> Self {
+ Self::with_entries(Vec::new())
+ }
+
+ /// Creates a new [`Menu`] with the given entries.
+ pub fn with_entries(entries: Vec<Entry<Message>>) -> Self {
+ Self { entries }
+ }
+
+ /// Adds an [`Entry`] to the [`Menu`].
+ pub fn push(mut self, entry: Entry<Message>) -> Self {
+ self.entries.push(entry);
+ self
+ }
+
+ /// Returns a [`MenuEntry`] iterator.
+ pub fn iter(self) -> impl Iterator<Item = Entry<Message>> {
+ self.entries.into_iter()
+ }
+}
+
+/// Represents one of the possible entries used to build a [`Menu`].
+#[derive(Debug, Clone, PartialEq)]
+pub enum Entry<Message> {
+ /// Item for a [`Menu`]
+ Item {
+ /// The title of the item
+ content: String,
+ /// The [`Hotkey`] to activate the item, if any
+ hotkey: Option<Hotkey>,
+ /// The message generated when the item is activated
+ on_activation: Message,
+ },
+ /// Dropdown for a [`Menu`]
+ Dropdown {
+ /// Title of the dropdown
+ content: String,
+ /// The submenu of the dropdown
+ submenu: Menu<Message>,
+ },
+ /// Separator for a [`Menu`]
+ Separator,
+}
+
+impl<Message> Entry<Message> {
+ /// Creates an [`Entry::Item`].
+ pub fn item<S: Into<String>>(
+ content: S,
+ hotkey: impl Into<Option<Hotkey>>,
+ on_activation: Message,
+ ) -> Self {
+ let content = content.into();
+ let hotkey = hotkey.into();
+
+ Entry::Item {
+ content,
+ hotkey,
+ on_activation,
+ }
+ }
+
+ /// Creates an [`Entry::Dropdown`].
+ pub fn dropdown<S: Into<String>>(
+ content: S,
+ submenu: Menu<Message>,
+ ) -> Self {
+ let content = content.into();
+
+ Entry::Dropdown { content, submenu }
+ }
+}