Skip to main content

fret_runtime/menu/
patch.rs

1use serde::Deserialize;
2
3use super::{MenuBar, MenuItem, MenuRole};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum MenuBarConfig {
7    Replace(MenuBar),
8    Patch(MenuBarPatch),
9}
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct MenuBarPatch {
13    pub ops: Vec<MenuBarPatchOp>,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
17#[serde(untagged)]
18pub enum MenuTarget {
19    /// Top-level menu title (back-compat with v1).
20    Title(String),
21    /// Menu path: `["File", "Recent"]` resolves to the `Recent` submenu under the `File` menu.
22    Path(Vec<String>),
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
26#[serde(untagged)]
27pub enum ItemAnchor {
28    /// Anchor by command id (back-compat with v1).
29    Command(String),
30    /// Anchor by zero-based item index (useful for separators and submenus).
31    Index(usize),
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
35#[serde(untagged)]
36pub enum ItemSelector {
37    /// Back-compat: a command id string or a numeric index.
38    Anchor(ItemAnchor),
39    /// Explicit selector for non-command items (e.g. submenus).
40    Typed(ItemSelectorTyped),
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
44#[serde(tag = "type", rename_all = "snake_case")]
45pub enum ItemSelectorTyped {
46    /// Select the first submenu item with the given title.
47    ///
48    /// Note: if multiple submenus share the same title, prefer using an index anchor instead.
49    Submenu { title: String },
50    /// Select the first label item with the given title.
51    ///
52    /// Note: if multiple labels share the same title, prefer using an index anchor instead.
53    Label { title: String },
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub enum MenuBarPatchOp {
58    AppendMenu {
59        title: String,
60        role: Option<MenuRole>,
61        mnemonic: Option<char>,
62        items: Vec<MenuItem>,
63    },
64    InsertMenuBefore {
65        title: String,
66        role: Option<MenuRole>,
67        mnemonic: Option<char>,
68        before: String,
69        items: Vec<MenuItem>,
70    },
71    InsertMenuAfter {
72        title: String,
73        role: Option<MenuRole>,
74        mnemonic: Option<char>,
75        after: String,
76        items: Vec<MenuItem>,
77    },
78    RemoveMenu {
79        title: String,
80    },
81    RenameMenu {
82        from: String,
83        to: String,
84    },
85    MoveMenuBefore {
86        title: String,
87        before: String,
88    },
89    MoveMenuAfter {
90        title: String,
91        after: String,
92    },
93
94    RemoveAt {
95        menu: MenuTarget,
96        at: ItemSelector,
97    },
98    MoveAtBefore {
99        menu: MenuTarget,
100        at: ItemSelector,
101        before: ItemSelector,
102    },
103    MoveAtAfter {
104        menu: MenuTarget,
105        at: ItemSelector,
106        after: ItemSelector,
107    },
108
109    RemoveItem {
110        menu: MenuTarget,
111        command: String,
112    },
113    InsertItemBefore {
114        menu: MenuTarget,
115        before: ItemAnchor,
116        item: MenuItem,
117    },
118    InsertItemAfter {
119        menu: MenuTarget,
120        after: ItemAnchor,
121        item: MenuItem,
122    },
123    PrependItem {
124        menu: MenuTarget,
125        item: MenuItem,
126    },
127    AppendItem {
128        menu: MenuTarget,
129        item: MenuItem,
130    },
131    MoveItemBefore {
132        menu: MenuTarget,
133        command: String,
134        before: ItemAnchor,
135    },
136    MoveItemAfter {
137        menu: MenuTarget,
138        command: String,
139        after: ItemAnchor,
140    },
141}