snora_core/menu.rs
1//! Header menus (File / Edit / View / ... drop-downs).
2//!
3//! A menu is a **pure data contract**. The application supplies a list of
4//! [`Menu`] values, the engine renders them into a header bar, and
5//! interaction is reported back via [`MenuAction`] messages. snora-core
6//! has no opinion on how the menu is rendered.
7//!
8//! `MenuId` and `MenuItemId` are application-defined types. They must
9//! implement `Clone` for message dispatch and `PartialEq` for tracking
10//! which menu is currently open.
11//!
12//! The recommended pattern is a pair of application-owned enums:
13//!
14//! ```rust
15//! #[derive(Clone, Debug, PartialEq, Eq)]
16//! enum MyMenuId { File, View, Help }
17//!
18//! #[derive(Clone, Debug, PartialEq, Eq)]
19//! enum MyMenuItemId { New, Open, Quit, ToggleLogs, About }
20//! ```
21
22use std::fmt::Debug;
23
24use crate::icon::Icon;
25
26/// An event emitted by a header menu.
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum MenuAction<MenuId, MenuItemId> {
29 /// The menu header (not an item) was pressed. Convention: toggle open /
30 /// closed, or switch the currently-open menu.
31 MenuPressed(MenuId),
32
33 /// An item within a menu was chosen.
34 MenuItemPressed {
35 /// Id of the parent menu.
36 menu_id: MenuId,
37 /// Id of the chosen item.
38 menu_item_id: MenuItemId,
39 },
40}
41
42/// A top-level menu in the header (e.g. "File", "View").
43#[derive(Debug, Clone)]
44pub struct Menu<MenuId, MenuItemId>
45where
46 MenuId: Clone + Debug + PartialEq,
47 MenuItemId: Clone + Debug,
48{
49 /// Application-defined identity of this menu.
50 pub id: MenuId,
51 /// Visible label (e.g. "File", "View").
52 pub label: String,
53 /// Optional icon shown next to the label.
54 pub icon: Option<Icon>,
55 /// Items shown in the dropdown when this menu is active.
56 pub items: Vec<MenuItem<MenuId, MenuItemId>>,
57}
58
59/// A single entry in a menu's dropdown.
60#[derive(Debug, Clone)]
61pub struct MenuItem<MenuId, MenuItemId>
62where
63 MenuId: Clone + Debug + PartialEq,
64 MenuItemId: Clone + Debug,
65{
66 /// The id of the parent menu. Stored on each item so that
67 /// [`MenuAction::MenuItemPressed`] can carry it without a second lookup.
68 pub menu_id: MenuId,
69 /// Application-defined identity of this item.
70 pub id: MenuItemId,
71 /// Visible label.
72 pub label: String,
73 /// Optional icon shown before the label.
74 pub icon: Option<Icon>,
75}