zng/
menu.rs

1#![cfg(feature = "menu")]
2
3//! Menu widgets, properties and other types.
4//!
5//! ```no_run
6//! use zng::prelude::*;
7//! # APP.defaults().run_window(async {
8//!
9//! fn main_menu() -> UiNode {
10//!     Menu!(ui_vec![
11//!         SubMenu!(
12//!             "File",
13//!             ui_vec![
14//!                 Button!(zng::app::NEW_CMD.scoped(WINDOW.id())),
15//!                 Button!(zng::app::OPEN_CMD.scoped(WINDOW.id())),
16//!                 Toggle! {
17//!                     child = Text!("Auto Save");
18//!                     checked = var(true);
19//!                 },
20//!                 Hr!(),
21//!                 SubMenu!(
22//!                     "Recent",
23//!                     (0..10).map(|i| Button! {
24//!                         child = Text!(formatx!("recent file {i}"));
25//!                     })
26//!                 ),
27//!                 Hr!(),
28//!                 Button!(zng::app::EXIT_CMD),
29//!             ]
30//!         ),
31//!         SubMenu!(
32//!             "Help",
33//!             ui_vec![Button! {
34//!                 child = Text!("About");
35//!                 on_click = hn!(|_| {});
36//!             }]
37//!         ),
38//!     ])
39//! }
40//!
41//! Window! {
42//!     child_top = main_menu();
43//!     zng::app::on_new = hn!(|_| {});
44//!     zng::app::on_open = hn!(|_| {});
45//!     // ..
46//! }
47//! # });
48//! ```
49//!
50//! The example above declares a [`Menu!`](struct@Menu) for a window, it demonstrates nested [`SubMenu!`](struct@sub::SubMenu),
51//! and menu items, [`Button!`](struct@crate::button::Button),
52//! [`Toggle!`](struct@crate::toggle::Toggle) and [`Hr!`](struct@crate::rule_line::hr::Hr). There is no menu item widget,
53//! the `SubMenu!` widget re-styles button and toggle.
54//!
55//! # Context Menu
56//!
57//! This module also provides a context menu. The example below declares a context menu for the window, it will show
58//! on context click, that is, by right-clicking the window, long pressing it or pressing the context menu key.
59//!
60//! ```
61//! use zng::prelude::*;
62//! # fn demo() {
63//!
64//! # let _ =
65//! Window! {
66//!     context_menu = ContextMenu!(ui_vec![
67//!         Button!(zng::app::NEW_CMD.scoped(WINDOW.id())),
68//!         Button!(zng::app::OPEN_CMD.scoped(WINDOW.id())),
69//!         Toggle! {
70//!             child = Text!("Auto Save");
71//!             checked = var(true);
72//!         },
73//!         Hr!(),
74//!         SubMenu!(
75//!             "Help",
76//!             ui_vec![Button! {
77//!                 child = Text!("About");
78//!                 on_click = hn!(|_| {});
79//!             }]
80//!         ),
81//!         Hr!(),
82//!         Button!(zng::app::EXIT_CMD),
83//!     ]);
84//! }
85//! # ; }
86//! ```
87//!
88//! # Full API
89//!
90//! See [`zng_wgt_menu`] for the full widget API.
91
92pub use zng_wgt_menu::{ButtonStyle, IconButtonStyle, Menu, ToggleStyle, icon, icon_fn, panel_fn, shortcut_txt, style_fn};
93
94use crate::widget::{widget, widget_set};
95
96/// Default [`Menu!`] style.
97///
98/// Extends [`zng_wgt_menu::DefaultStyle!`] to cover more widgets. This is set as default in the `APP.default` using a window root extender.
99///
100/// [`Menu!`]: struct@Menu
101/// [`zng_wgt_menu::DefaultStyle!`]: struct@zng_wgt_menu::DefaultStyle
102#[widget($crate::menu::DefaultStyle)]
103pub struct DefaultStyle(zng_wgt_menu::DefaultStyle);
104impl DefaultStyle {
105    fn widget_intrinsic(&mut self) {
106        widget_set! {
107            self;
108            #[cfg(feature = "text_input")]
109            crate::text_input::style_fn = crate::style::style_fn!(|_| TextInputStyle!());
110        }
111    }
112}
113
114/// Style applied to all [`TextInput!`] widgets inside [`Menu!`] root.
115///
116/// Gives the input a *toolbar-item* look.
117///
118/// [`TextInput!`]: struct@crate::text_input::TextInput
119/// [`Menu!`]: struct@Menu
120#[cfg(feature = "text_input")]
121#[widget($crate::menu::TextInputStyle)]
122pub struct TextInputStyle(crate::text_input::DefaultStyle);
123#[cfg(feature = "text_input")]
124impl TextInputStyle {
125    fn widget_intrinsic(&mut self) {
126        widget_set! {
127            self;
128            zng::layout::padding = 2;
129            // return focus on enter
130            zng::keyboard::on_pre_key_down = zng::handler::hn!(|args| {
131                use zng::event::AnyEventArgs as _;
132                args.propagation().stop();
133                zng::focus::FOCUS.focus_exit();
134            });
135        }
136    }
137}
138
139/// Submenu widget and properties.
140///
141/// See [`zng_wgt_menu::sub`] for the full widget API.
142pub mod sub {
143    pub use zng_wgt_menu::sub::{
144        ButtonStyle, DefaultStyle, SubMenu, SubMenuAncestors, SubMenuStyle, SubMenuWidgetInfoExt, ToggleStyle, TouchButtonStyle,
145        column_width_padding, end_column, end_column_fn, end_column_width, hover_open_delay, is_open, start_column, start_column_fn,
146        start_column_width,
147    };
148}
149
150/// Context menu widget and properties.
151///
152/// See [`zng_wgt_menu::context`] for the full widget API.
153pub mod context {
154    pub use zng_wgt_menu::context::{
155        ContextMenu, ContextMenuArgs, DefaultStyle, TouchStyle, context_menu, context_menu_anchor, context_menu_fn, disabled_context_menu,
156        disabled_context_menu_fn, panel_fn, style_fn, touch_style_fn,
157    };
158}
159
160/// Sub-menu popup widget and properties.
161///
162/// See [`zng_wgt_menu::popup`] for the full widget API.
163pub mod popup {
164    pub use zng_wgt_menu::popup::{DefaultStyle, SubMenuPopup, panel_fn, style_fn};
165}