pub struct Menu {
pub label: String,
pub items: Vec<MenuItemNode>,
}Expand description
A menu in the menu bar.
Fields§
§label: StringDisplay label for the menu.
items: Vec<MenuItemNode>Items in this menu.
Implementations§
Source§impl Menu
impl Menu
Sourcepub fn new(label: impl Into<String>) -> Self
pub fn new(label: impl Into<String>) -> Self
Create a new menu with the given label.
Examples found in repository?
examples/20_menu_bar.rs (line 99)
26 fn render(&self, cx: Scope) -> View {
27 let show_help = state!(cx, || false);
28
29 // F1 toggles help
30 cx.use_command(
31 KeyBinding::key(KeyCode::F(1)),
32 with!(show_help => move || show_help.update(|v| *v = !*v)),
33 );
34
35 // Menu state
36 let active_menu = state!(cx, || Option::<usize>::None);
37 let highlighted_menu = state!(cx, || 0usize);
38 let selected_item = state!(cx, || 0usize);
39
40 // App state
41 let message = state!(cx, || "Use Tab to focus menu bar, then Enter to open".to_string());
42 let counter = state!(cx, || 0i32);
43
44 // Command handler - executes menu commands
45 let handle_command = with!(message, counter, active_menu, selected_item => move |cmd_id: &'static str| {
46 let msg = match cmd_id {
47 "file.new" => "Created new file".to_string(),
48 "file.open" => "Opening file...".to_string(),
49 "file.save" => "File saved".to_string(),
50 "file.quit" => "Use Ctrl+Q to quit".to_string(),
51 "edit.undo" => "Undone".to_string(),
52 "edit.redo" => "Redone".to_string(),
53 "edit.cut" => "Cut to clipboard".to_string(),
54 "edit.copy" => "Copied to clipboard".to_string(),
55 "edit.paste" => "Pasted from clipboard".to_string(),
56 "counter.increment" => {
57 counter.update(|n| *n += 1);
58 format!("Counter: {}", counter.get())
59 }
60 "counter.decrement" => {
61 counter.update(|n| *n -= 1);
62 format!("Counter: {}", counter.get())
63 }
64 "counter.reset" => {
65 counter.set(0);
66 "Counter reset".to_string()
67 }
68 _ => format!("Unknown: {}", cmd_id),
69 };
70 message.set(msg);
71 // Close menu after executing command
72 active_menu.set(None);
73 selected_item.set(0);
74 });
75
76 // Menu change handler - opens/closes menus
77 let on_menu_change = with!(active_menu, highlighted_menu, selected_item => move |idx: usize| {
78 if active_menu.get() == Some(idx) {
79 // Clicking same menu toggles it closed
80 active_menu.set(None);
81 } else {
82 active_menu.set(Some(idx));
83 highlighted_menu.set(idx); // Keep highlight in sync
84 selected_item.set(0);
85 }
86 });
87
88 // Highlight change handler - arrow key navigation when no menu is open
89 let on_highlight_change = with!(highlighted_menu => move |idx: usize| {
90 highlighted_menu.set(idx);
91 });
92
93 // Item change handler - navigates within menu
94 let on_item_change = with!(selected_item => move |idx: usize| {
95 selected_item.set(idx);
96 });
97
98 // Build menus
99 let file_menu = Menu::new("File")
100 .command_with_shortcut("file.new", "New", "Ctrl+N")
101 .command_with_shortcut("file.open", "Open", "Ctrl+O")
102 .command_with_shortcut("file.save", "Save", "Ctrl+S")
103 .separator()
104 .command_with_shortcut("file.quit", "Quit", "Ctrl+Q");
105
106 let edit_menu = Menu::new("Edit")
107 .command_with_shortcut("edit.undo", "Undo", "Ctrl+Z")
108 .command_with_shortcut("edit.redo", "Redo", "Ctrl+Y")
109 .separator()
110 .command_with_shortcut("edit.cut", "Cut", "Ctrl+X")
111 .command_with_shortcut("edit.copy", "Copy", "Ctrl+C")
112 .command_with_shortcut("edit.paste", "Paste", "Ctrl+V");
113
114 let counter_menu = Menu::new("Counter")
115 .command("counter.increment", "Increment")
116 .command("counter.decrement", "Decrement")
117 .separator()
118 .command("counter.reset", "Reset to Zero");
119
120 View::vstack()
121 .child(
122 View::menu_bar()
123 .menu(file_menu)
124 .menu(edit_menu)
125 .menu(counter_menu)
126 .active_menu(active_menu.get())
127 .highlighted_menu(highlighted_menu.get())
128 .selected_item(selected_item.get())
129 .on_select(handle_command)
130 .on_menu_change(on_menu_change)
131 .on_highlight_change(on_highlight_change)
132 .on_item_change(on_item_change)
133 .build(),
134 )
135 .child(
136 View::boxed()
137 .flex(1)
138 .border(true)
139 .padding(2)
140 .child(
141 View::vstack()
142 .spacing(1)
143 .child(View::styled_text("Menu Bar Demo").bold().build())
144 .child(
145 View::styled_text(format!("Counter: {}", counter.get()))
146 .color(Color::Cyan)
147 .bold()
148 .build(),
149 )
150 .child(
151 View::styled_text(format!("Status: {}", message.get()))
152 .dim()
153 .build(),
154 )
155 .child(View::spacer())
156 .child(View::styled_text("Keyboard Navigation:").bold().build())
157 .child(View::text(" Tab Focus menu bar"))
158 .child(View::text(" Enter Open menu / Execute item"))
159 .child(View::text(" Up/Down Navigate menu items"))
160 .child(View::text(" Left/Right Switch between menus"))
161 .child(View::text(" Escape Close menu"))
162 .child(View::text(" Ctrl+Q Quit"))
163 .child(View::text(" F1 Help"))
164 .build(),
165 )
166 .build(),
167 )
168 .child(
169 View::modal()
170 .visible(show_help.get())
171 .title("Example 20: Menu Bar")
172 .on_dismiss(with!(show_help => move || show_help.set(false)))
173 .child(
174 View::vstack()
175 .child(View::styled_text("What you're seeing").bold().build())
176 .child(View::text("• Dropdown menu bar with keyboard nav"))
177 .child(View::text("• Menu items with shortcuts"))
178 .child(View::text("• Separators in menus"))
179 .child(View::gap(1))
180 .child(View::styled_text("Key concepts").bold().build())
181 .child(View::text("• View::menu_bar() creates menu system"))
182 .child(View::text("• Menu::new().command() adds items"))
183 .child(View::text("• .command_with_shortcut() shows key hints"))
184 .child(View::text("• on_select receives command ID"))
185 .child(View::gap(1))
186 .child(View::styled_text("Try this").bold().build())
187 .child(View::text("• Tab to menu, Enter to open"))
188 .child(View::text("• Arrow keys navigate menus"))
189 .child(View::text("• Try the Counter menu"))
190 .child(View::gap(1))
191 .child(View::styled_text("Next up").bold().build())
192 .child(View::text("→ 21_toasts: toast notifications"))
193 .child(View::gap(1))
194 .child(View::styled_text("Press Escape to close").dim().build())
195 .build(),
196 )
197 .build(),
198 )
199 .build()
200 }Sourcepub fn item(self, item: MenuItemNode) -> Self
pub fn item(self, item: MenuItemNode) -> Self
Add an item to the menu.
Sourcepub fn command(self, id: &'static str, label: impl Into<String>) -> Self
pub fn command(self, id: &'static str, label: impl Into<String>) -> Self
Add a command item.
Examples found in repository?
examples/20_menu_bar.rs (line 115)
26 fn render(&self, cx: Scope) -> View {
27 let show_help = state!(cx, || false);
28
29 // F1 toggles help
30 cx.use_command(
31 KeyBinding::key(KeyCode::F(1)),
32 with!(show_help => move || show_help.update(|v| *v = !*v)),
33 );
34
35 // Menu state
36 let active_menu = state!(cx, || Option::<usize>::None);
37 let highlighted_menu = state!(cx, || 0usize);
38 let selected_item = state!(cx, || 0usize);
39
40 // App state
41 let message = state!(cx, || "Use Tab to focus menu bar, then Enter to open".to_string());
42 let counter = state!(cx, || 0i32);
43
44 // Command handler - executes menu commands
45 let handle_command = with!(message, counter, active_menu, selected_item => move |cmd_id: &'static str| {
46 let msg = match cmd_id {
47 "file.new" => "Created new file".to_string(),
48 "file.open" => "Opening file...".to_string(),
49 "file.save" => "File saved".to_string(),
50 "file.quit" => "Use Ctrl+Q to quit".to_string(),
51 "edit.undo" => "Undone".to_string(),
52 "edit.redo" => "Redone".to_string(),
53 "edit.cut" => "Cut to clipboard".to_string(),
54 "edit.copy" => "Copied to clipboard".to_string(),
55 "edit.paste" => "Pasted from clipboard".to_string(),
56 "counter.increment" => {
57 counter.update(|n| *n += 1);
58 format!("Counter: {}", counter.get())
59 }
60 "counter.decrement" => {
61 counter.update(|n| *n -= 1);
62 format!("Counter: {}", counter.get())
63 }
64 "counter.reset" => {
65 counter.set(0);
66 "Counter reset".to_string()
67 }
68 _ => format!("Unknown: {}", cmd_id),
69 };
70 message.set(msg);
71 // Close menu after executing command
72 active_menu.set(None);
73 selected_item.set(0);
74 });
75
76 // Menu change handler - opens/closes menus
77 let on_menu_change = with!(active_menu, highlighted_menu, selected_item => move |idx: usize| {
78 if active_menu.get() == Some(idx) {
79 // Clicking same menu toggles it closed
80 active_menu.set(None);
81 } else {
82 active_menu.set(Some(idx));
83 highlighted_menu.set(idx); // Keep highlight in sync
84 selected_item.set(0);
85 }
86 });
87
88 // Highlight change handler - arrow key navigation when no menu is open
89 let on_highlight_change = with!(highlighted_menu => move |idx: usize| {
90 highlighted_menu.set(idx);
91 });
92
93 // Item change handler - navigates within menu
94 let on_item_change = with!(selected_item => move |idx: usize| {
95 selected_item.set(idx);
96 });
97
98 // Build menus
99 let file_menu = Menu::new("File")
100 .command_with_shortcut("file.new", "New", "Ctrl+N")
101 .command_with_shortcut("file.open", "Open", "Ctrl+O")
102 .command_with_shortcut("file.save", "Save", "Ctrl+S")
103 .separator()
104 .command_with_shortcut("file.quit", "Quit", "Ctrl+Q");
105
106 let edit_menu = Menu::new("Edit")
107 .command_with_shortcut("edit.undo", "Undo", "Ctrl+Z")
108 .command_with_shortcut("edit.redo", "Redo", "Ctrl+Y")
109 .separator()
110 .command_with_shortcut("edit.cut", "Cut", "Ctrl+X")
111 .command_with_shortcut("edit.copy", "Copy", "Ctrl+C")
112 .command_with_shortcut("edit.paste", "Paste", "Ctrl+V");
113
114 let counter_menu = Menu::new("Counter")
115 .command("counter.increment", "Increment")
116 .command("counter.decrement", "Decrement")
117 .separator()
118 .command("counter.reset", "Reset to Zero");
119
120 View::vstack()
121 .child(
122 View::menu_bar()
123 .menu(file_menu)
124 .menu(edit_menu)
125 .menu(counter_menu)
126 .active_menu(active_menu.get())
127 .highlighted_menu(highlighted_menu.get())
128 .selected_item(selected_item.get())
129 .on_select(handle_command)
130 .on_menu_change(on_menu_change)
131 .on_highlight_change(on_highlight_change)
132 .on_item_change(on_item_change)
133 .build(),
134 )
135 .child(
136 View::boxed()
137 .flex(1)
138 .border(true)
139 .padding(2)
140 .child(
141 View::vstack()
142 .spacing(1)
143 .child(View::styled_text("Menu Bar Demo").bold().build())
144 .child(
145 View::styled_text(format!("Counter: {}", counter.get()))
146 .color(Color::Cyan)
147 .bold()
148 .build(),
149 )
150 .child(
151 View::styled_text(format!("Status: {}", message.get()))
152 .dim()
153 .build(),
154 )
155 .child(View::spacer())
156 .child(View::styled_text("Keyboard Navigation:").bold().build())
157 .child(View::text(" Tab Focus menu bar"))
158 .child(View::text(" Enter Open menu / Execute item"))
159 .child(View::text(" Up/Down Navigate menu items"))
160 .child(View::text(" Left/Right Switch between menus"))
161 .child(View::text(" Escape Close menu"))
162 .child(View::text(" Ctrl+Q Quit"))
163 .child(View::text(" F1 Help"))
164 .build(),
165 )
166 .build(),
167 )
168 .child(
169 View::modal()
170 .visible(show_help.get())
171 .title("Example 20: Menu Bar")
172 .on_dismiss(with!(show_help => move || show_help.set(false)))
173 .child(
174 View::vstack()
175 .child(View::styled_text("What you're seeing").bold().build())
176 .child(View::text("• Dropdown menu bar with keyboard nav"))
177 .child(View::text("• Menu items with shortcuts"))
178 .child(View::text("• Separators in menus"))
179 .child(View::gap(1))
180 .child(View::styled_text("Key concepts").bold().build())
181 .child(View::text("• View::menu_bar() creates menu system"))
182 .child(View::text("• Menu::new().command() adds items"))
183 .child(View::text("• .command_with_shortcut() shows key hints"))
184 .child(View::text("• on_select receives command ID"))
185 .child(View::gap(1))
186 .child(View::styled_text("Try this").bold().build())
187 .child(View::text("• Tab to menu, Enter to open"))
188 .child(View::text("• Arrow keys navigate menus"))
189 .child(View::text("• Try the Counter menu"))
190 .child(View::gap(1))
191 .child(View::styled_text("Next up").bold().build())
192 .child(View::text("→ 21_toasts: toast notifications"))
193 .child(View::gap(1))
194 .child(View::styled_text("Press Escape to close").dim().build())
195 .build(),
196 )
197 .build(),
198 )
199 .build()
200 }Sourcepub fn command_with_shortcut(
self,
id: &'static str,
label: impl Into<String>,
shortcut: impl Into<String>,
) -> Self
pub fn command_with_shortcut( self, id: &'static str, label: impl Into<String>, shortcut: impl Into<String>, ) -> Self
Add a command item with shortcut display.
Examples found in repository?
examples/20_menu_bar.rs (line 100)
26 fn render(&self, cx: Scope) -> View {
27 let show_help = state!(cx, || false);
28
29 // F1 toggles help
30 cx.use_command(
31 KeyBinding::key(KeyCode::F(1)),
32 with!(show_help => move || show_help.update(|v| *v = !*v)),
33 );
34
35 // Menu state
36 let active_menu = state!(cx, || Option::<usize>::None);
37 let highlighted_menu = state!(cx, || 0usize);
38 let selected_item = state!(cx, || 0usize);
39
40 // App state
41 let message = state!(cx, || "Use Tab to focus menu bar, then Enter to open".to_string());
42 let counter = state!(cx, || 0i32);
43
44 // Command handler - executes menu commands
45 let handle_command = with!(message, counter, active_menu, selected_item => move |cmd_id: &'static str| {
46 let msg = match cmd_id {
47 "file.new" => "Created new file".to_string(),
48 "file.open" => "Opening file...".to_string(),
49 "file.save" => "File saved".to_string(),
50 "file.quit" => "Use Ctrl+Q to quit".to_string(),
51 "edit.undo" => "Undone".to_string(),
52 "edit.redo" => "Redone".to_string(),
53 "edit.cut" => "Cut to clipboard".to_string(),
54 "edit.copy" => "Copied to clipboard".to_string(),
55 "edit.paste" => "Pasted from clipboard".to_string(),
56 "counter.increment" => {
57 counter.update(|n| *n += 1);
58 format!("Counter: {}", counter.get())
59 }
60 "counter.decrement" => {
61 counter.update(|n| *n -= 1);
62 format!("Counter: {}", counter.get())
63 }
64 "counter.reset" => {
65 counter.set(0);
66 "Counter reset".to_string()
67 }
68 _ => format!("Unknown: {}", cmd_id),
69 };
70 message.set(msg);
71 // Close menu after executing command
72 active_menu.set(None);
73 selected_item.set(0);
74 });
75
76 // Menu change handler - opens/closes menus
77 let on_menu_change = with!(active_menu, highlighted_menu, selected_item => move |idx: usize| {
78 if active_menu.get() == Some(idx) {
79 // Clicking same menu toggles it closed
80 active_menu.set(None);
81 } else {
82 active_menu.set(Some(idx));
83 highlighted_menu.set(idx); // Keep highlight in sync
84 selected_item.set(0);
85 }
86 });
87
88 // Highlight change handler - arrow key navigation when no menu is open
89 let on_highlight_change = with!(highlighted_menu => move |idx: usize| {
90 highlighted_menu.set(idx);
91 });
92
93 // Item change handler - navigates within menu
94 let on_item_change = with!(selected_item => move |idx: usize| {
95 selected_item.set(idx);
96 });
97
98 // Build menus
99 let file_menu = Menu::new("File")
100 .command_with_shortcut("file.new", "New", "Ctrl+N")
101 .command_with_shortcut("file.open", "Open", "Ctrl+O")
102 .command_with_shortcut("file.save", "Save", "Ctrl+S")
103 .separator()
104 .command_with_shortcut("file.quit", "Quit", "Ctrl+Q");
105
106 let edit_menu = Menu::new("Edit")
107 .command_with_shortcut("edit.undo", "Undo", "Ctrl+Z")
108 .command_with_shortcut("edit.redo", "Redo", "Ctrl+Y")
109 .separator()
110 .command_with_shortcut("edit.cut", "Cut", "Ctrl+X")
111 .command_with_shortcut("edit.copy", "Copy", "Ctrl+C")
112 .command_with_shortcut("edit.paste", "Paste", "Ctrl+V");
113
114 let counter_menu = Menu::new("Counter")
115 .command("counter.increment", "Increment")
116 .command("counter.decrement", "Decrement")
117 .separator()
118 .command("counter.reset", "Reset to Zero");
119
120 View::vstack()
121 .child(
122 View::menu_bar()
123 .menu(file_menu)
124 .menu(edit_menu)
125 .menu(counter_menu)
126 .active_menu(active_menu.get())
127 .highlighted_menu(highlighted_menu.get())
128 .selected_item(selected_item.get())
129 .on_select(handle_command)
130 .on_menu_change(on_menu_change)
131 .on_highlight_change(on_highlight_change)
132 .on_item_change(on_item_change)
133 .build(),
134 )
135 .child(
136 View::boxed()
137 .flex(1)
138 .border(true)
139 .padding(2)
140 .child(
141 View::vstack()
142 .spacing(1)
143 .child(View::styled_text("Menu Bar Demo").bold().build())
144 .child(
145 View::styled_text(format!("Counter: {}", counter.get()))
146 .color(Color::Cyan)
147 .bold()
148 .build(),
149 )
150 .child(
151 View::styled_text(format!("Status: {}", message.get()))
152 .dim()
153 .build(),
154 )
155 .child(View::spacer())
156 .child(View::styled_text("Keyboard Navigation:").bold().build())
157 .child(View::text(" Tab Focus menu bar"))
158 .child(View::text(" Enter Open menu / Execute item"))
159 .child(View::text(" Up/Down Navigate menu items"))
160 .child(View::text(" Left/Right Switch between menus"))
161 .child(View::text(" Escape Close menu"))
162 .child(View::text(" Ctrl+Q Quit"))
163 .child(View::text(" F1 Help"))
164 .build(),
165 )
166 .build(),
167 )
168 .child(
169 View::modal()
170 .visible(show_help.get())
171 .title("Example 20: Menu Bar")
172 .on_dismiss(with!(show_help => move || show_help.set(false)))
173 .child(
174 View::vstack()
175 .child(View::styled_text("What you're seeing").bold().build())
176 .child(View::text("• Dropdown menu bar with keyboard nav"))
177 .child(View::text("• Menu items with shortcuts"))
178 .child(View::text("• Separators in menus"))
179 .child(View::gap(1))
180 .child(View::styled_text("Key concepts").bold().build())
181 .child(View::text("• View::menu_bar() creates menu system"))
182 .child(View::text("• Menu::new().command() adds items"))
183 .child(View::text("• .command_with_shortcut() shows key hints"))
184 .child(View::text("• on_select receives command ID"))
185 .child(View::gap(1))
186 .child(View::styled_text("Try this").bold().build())
187 .child(View::text("• Tab to menu, Enter to open"))
188 .child(View::text("• Arrow keys navigate menus"))
189 .child(View::text("• Try the Counter menu"))
190 .child(View::gap(1))
191 .child(View::styled_text("Next up").bold().build())
192 .child(View::text("→ 21_toasts: toast notifications"))
193 .child(View::gap(1))
194 .child(View::styled_text("Press Escape to close").dim().build())
195 .build(),
196 )
197 .build(),
198 )
199 .build()
200 }Sourcepub fn separator(self) -> Self
pub fn separator(self) -> Self
Add a separator.
Examples found in repository?
examples/20_menu_bar.rs (line 103)
26 fn render(&self, cx: Scope) -> View {
27 let show_help = state!(cx, || false);
28
29 // F1 toggles help
30 cx.use_command(
31 KeyBinding::key(KeyCode::F(1)),
32 with!(show_help => move || show_help.update(|v| *v = !*v)),
33 );
34
35 // Menu state
36 let active_menu = state!(cx, || Option::<usize>::None);
37 let highlighted_menu = state!(cx, || 0usize);
38 let selected_item = state!(cx, || 0usize);
39
40 // App state
41 let message = state!(cx, || "Use Tab to focus menu bar, then Enter to open".to_string());
42 let counter = state!(cx, || 0i32);
43
44 // Command handler - executes menu commands
45 let handle_command = with!(message, counter, active_menu, selected_item => move |cmd_id: &'static str| {
46 let msg = match cmd_id {
47 "file.new" => "Created new file".to_string(),
48 "file.open" => "Opening file...".to_string(),
49 "file.save" => "File saved".to_string(),
50 "file.quit" => "Use Ctrl+Q to quit".to_string(),
51 "edit.undo" => "Undone".to_string(),
52 "edit.redo" => "Redone".to_string(),
53 "edit.cut" => "Cut to clipboard".to_string(),
54 "edit.copy" => "Copied to clipboard".to_string(),
55 "edit.paste" => "Pasted from clipboard".to_string(),
56 "counter.increment" => {
57 counter.update(|n| *n += 1);
58 format!("Counter: {}", counter.get())
59 }
60 "counter.decrement" => {
61 counter.update(|n| *n -= 1);
62 format!("Counter: {}", counter.get())
63 }
64 "counter.reset" => {
65 counter.set(0);
66 "Counter reset".to_string()
67 }
68 _ => format!("Unknown: {}", cmd_id),
69 };
70 message.set(msg);
71 // Close menu after executing command
72 active_menu.set(None);
73 selected_item.set(0);
74 });
75
76 // Menu change handler - opens/closes menus
77 let on_menu_change = with!(active_menu, highlighted_menu, selected_item => move |idx: usize| {
78 if active_menu.get() == Some(idx) {
79 // Clicking same menu toggles it closed
80 active_menu.set(None);
81 } else {
82 active_menu.set(Some(idx));
83 highlighted_menu.set(idx); // Keep highlight in sync
84 selected_item.set(0);
85 }
86 });
87
88 // Highlight change handler - arrow key navigation when no menu is open
89 let on_highlight_change = with!(highlighted_menu => move |idx: usize| {
90 highlighted_menu.set(idx);
91 });
92
93 // Item change handler - navigates within menu
94 let on_item_change = with!(selected_item => move |idx: usize| {
95 selected_item.set(idx);
96 });
97
98 // Build menus
99 let file_menu = Menu::new("File")
100 .command_with_shortcut("file.new", "New", "Ctrl+N")
101 .command_with_shortcut("file.open", "Open", "Ctrl+O")
102 .command_with_shortcut("file.save", "Save", "Ctrl+S")
103 .separator()
104 .command_with_shortcut("file.quit", "Quit", "Ctrl+Q");
105
106 let edit_menu = Menu::new("Edit")
107 .command_with_shortcut("edit.undo", "Undo", "Ctrl+Z")
108 .command_with_shortcut("edit.redo", "Redo", "Ctrl+Y")
109 .separator()
110 .command_with_shortcut("edit.cut", "Cut", "Ctrl+X")
111 .command_with_shortcut("edit.copy", "Copy", "Ctrl+C")
112 .command_with_shortcut("edit.paste", "Paste", "Ctrl+V");
113
114 let counter_menu = Menu::new("Counter")
115 .command("counter.increment", "Increment")
116 .command("counter.decrement", "Decrement")
117 .separator()
118 .command("counter.reset", "Reset to Zero");
119
120 View::vstack()
121 .child(
122 View::menu_bar()
123 .menu(file_menu)
124 .menu(edit_menu)
125 .menu(counter_menu)
126 .active_menu(active_menu.get())
127 .highlighted_menu(highlighted_menu.get())
128 .selected_item(selected_item.get())
129 .on_select(handle_command)
130 .on_menu_change(on_menu_change)
131 .on_highlight_change(on_highlight_change)
132 .on_item_change(on_item_change)
133 .build(),
134 )
135 .child(
136 View::boxed()
137 .flex(1)
138 .border(true)
139 .padding(2)
140 .child(
141 View::vstack()
142 .spacing(1)
143 .child(View::styled_text("Menu Bar Demo").bold().build())
144 .child(
145 View::styled_text(format!("Counter: {}", counter.get()))
146 .color(Color::Cyan)
147 .bold()
148 .build(),
149 )
150 .child(
151 View::styled_text(format!("Status: {}", message.get()))
152 .dim()
153 .build(),
154 )
155 .child(View::spacer())
156 .child(View::styled_text("Keyboard Navigation:").bold().build())
157 .child(View::text(" Tab Focus menu bar"))
158 .child(View::text(" Enter Open menu / Execute item"))
159 .child(View::text(" Up/Down Navigate menu items"))
160 .child(View::text(" Left/Right Switch between menus"))
161 .child(View::text(" Escape Close menu"))
162 .child(View::text(" Ctrl+Q Quit"))
163 .child(View::text(" F1 Help"))
164 .build(),
165 )
166 .build(),
167 )
168 .child(
169 View::modal()
170 .visible(show_help.get())
171 .title("Example 20: Menu Bar")
172 .on_dismiss(with!(show_help => move || show_help.set(false)))
173 .child(
174 View::vstack()
175 .child(View::styled_text("What you're seeing").bold().build())
176 .child(View::text("• Dropdown menu bar with keyboard nav"))
177 .child(View::text("• Menu items with shortcuts"))
178 .child(View::text("• Separators in menus"))
179 .child(View::gap(1))
180 .child(View::styled_text("Key concepts").bold().build())
181 .child(View::text("• View::menu_bar() creates menu system"))
182 .child(View::text("• Menu::new().command() adds items"))
183 .child(View::text("• .command_with_shortcut() shows key hints"))
184 .child(View::text("• on_select receives command ID"))
185 .child(View::gap(1))
186 .child(View::styled_text("Try this").bold().build())
187 .child(View::text("• Tab to menu, Enter to open"))
188 .child(View::text("• Arrow keys navigate menus"))
189 .child(View::text("• Try the Counter menu"))
190 .child(View::gap(1))
191 .child(View::styled_text("Next up").bold().build())
192 .child(View::text("→ 21_toasts: toast notifications"))
193 .child(View::gap(1))
194 .child(View::styled_text("Press Escape to close").dim().build())
195 .build(),
196 )
197 .build(),
198 )
199 .build()
200 }Trait Implementations§
Auto Trait Implementations§
impl Freeze for Menu
impl RefUnwindSafe for Menu
impl Send for Menu
impl Sync for Menu
impl Unpin for Menu
impl UnwindSafe for Menu
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Convert
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Convert
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.