summaryrefslogtreecommitdiffstats
path: root/native/src/menu.rs
blob: 6c73cb328bc8d16583936658d3b1844b6a06b55d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! 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> {
    items: Vec<MenuEntry<Message>>,
}

impl<Message> Menu<Message> {
    /// Creates an empty [`Menu`].
    pub fn new() -> Self {
        Menu { items: Vec::new() }
    }

    /// Adds an item to the [`Menu`].
    pub fn item<S: Into<String>>(
        mut self,
        content: S,
        hotkey: impl Into<Option<Hotkey>>,
        on_activation: Message,
    ) -> Self {
        let content = content.into();
        let hotkey = hotkey.into();

        self.items.push(MenuEntry::Item {
            on_activation,
            content,
            hotkey,
        });
        self
    }

    /// Adds a separator to the [`Menu`].
    pub fn separator(mut self) -> Self {
        self.items.push(MenuEntry::Separator);
        self
    }

    /// Adds a dropdown to the [`Menu`].
    pub fn dropdown<S: Into<String>>(
        mut self,
        content: S,
        submenu: Menu<Message>,
    ) -> Self {
        let content = content.into();

        self.items.push(MenuEntry::Dropdown { content, submenu });
        self
    }

    /// Returns a [`MenuEntry`] iterator.
    pub fn iter(self) -> std::vec::IntoIter<MenuEntry<Message>> {
        self.items.into_iter()
    }
}

/// Represents one of the possible entries used to build a [`Menu`].
#[derive(Debug, Clone, PartialEq)]
pub enum MenuEntry<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,
}