zng/
toggle.rs

1#![cfg(feature = "toggle")]
2
3//! Toggle button widget and styles for check box, combo box, radio button and switch button.
4//!
5//! The [`Toggle!`](struct@Toggle) widget has three states, `Some(true)`, `Some(false)` and `None`. How
6//! the widget toggles between this values is defined by what property is used to bind the state.
7//!
8//! The [`checked`](struct@Toggle#checked) property binds to a `bool` variable and toggles between `true` and `false` only.
9//! The example below makes use of the property.
10//!
11//! ```
12//! use zng::prelude::*;
13//! # fn example() {
14//!
15//! let checked = var(false);
16//! # let _ =
17//! Toggle! {
18//!     child = Text!(checked.map(|b| formatx!("checked = {b}")));
19//!     checked;
20//! }
21//! # ; }
22//! ```
23//!
24//! The [`checked_opt`](struct@Toggle#method.checked_opt) and [`tristate`](struct@Toggle#method.tristate) properties can be used to toggle
25//! between `Some(true)` and `Some(false)` and accept the `None` value, or with tristate enabled to include `None` in the toggle cycle.
26//! Note that even if tristate is not enabled the variable can be set to `None` from another source and the widget will display the
27//! `None` appearance.
28//!
29//! ```
30//! use zng::prelude::*;
31//! # fn example() {
32//!
33//! let checked = var(Some(false));
34//! # let _ =
35//! Toggle! {
36//!     child = Text!(checked.map(|b| formatx!("checked = {b:?}")));
37//!     tristate = true;
38//!     checked_opt = checked;
39//! }
40//! # ; }
41//! ```
42//!
43//! The [`selector`](fn@selector) and [`value`](struct@Toggle#method.value) properties can be used to have the toggle insert and
44//! remove a value from a contextual selection of values. The example below declares a stack with 10 toggle buttons each
45//! representing a value, the stack is also setup as a selector context for these toggle buttons, when each toggle button
46//! is clicked it replaces the selected value.
47//!
48//! Note that the toggle does not know what the selection actually is, the [`Selector`] type abstracts over multiple
49//! selection kinds, including custom implementations of [`SelectorImpl`].
50//!
51//! ```
52//! use zng::prelude::*;
53//! # fn example() {
54//!
55//! let selected_item = var(1_i32);
56//! # let _ =
57//! Stack! {
58//!     toggle::selector = toggle::Selector::single(selected_item.clone());
59//!
60//!     spacing = 5;
61//!     children =
62//!         (1..=10_i32)
63//!             .map(|i| {
64//!                 Toggle! {
65//!                     child = Text!("Item {i}");
66//!                     value::<i32> = i;
67//!                 }
68//!             })
69//!             .collect::<Vec<_>>(),
70//!     ;
71//! }
72//! # ; }
73//! ```
74//!
75//! Regardless of how the checked state of a toggle is defined the [`IS_CHECKED_VAR`] variable and [`is_checked`](fn@is_checked) property
76//! can be used to track the checked state of the widget. The example below defines a toggle that changes background color to green
77//! when it is in the `Some(true)` state.
78//!
79//! ```
80//! # use zng::prelude::*;
81//! # fn example() {
82//! # let _ =
83//! Toggle! {
84//!     checked = var(false);
85//!     // checked_opt = var(Some(false));
86//!     // value<i32> = 42;
87//!
88//!     widget::background_color = colors::RED;
89//!     when *#is_checked {
90//!         widget::background_color = colors::GREEN;
91//!     }
92//! }
93//! # ; }
94//! ```
95//!
96//! # Styles
97//!
98//! Toggle is a versatile widget, it can be styled to represent check boxes, switches, radio buttons and combo boxes.
99//!
100//! ## Check & Switch
101//!
102//! The [`CheckStyle!`](struct@CheckStyle) changes the toggle into a check box. The [`SwitchStyle!`](struct@SwitchStyle)
103//! changes the toggle into an on/off switch.
104//!
105//! ```
106//! use zng::prelude::*;
107//! # fn example() {
108//!
109//! # let _ =
110//! Toggle! {
111//!     child = Text!(toggle::IS_CHECKED_VAR.map(|&s| match s {
112//!         Some(true) => Txt::from("checked text"),
113//!         Some(false) => Txt::from("unchecked text"),
114//!         None => Txt::from(""),
115//!     }));
116//!     checked = var(false);
117//!     style_fn = toggle::SwitchStyle!();
118//! }
119//! # ; }
120//! ```
121//!
122//! The example above declares a toggle switch that changes the text depending on the state.
123//!
124//! ## Radio
125//!
126//! The [`RadioStyle!`](struct@RadioStyle) can be used in `value` toggle areas. The example below
127//! declares a stack that is a selector context and sets the toggle style for all toggle buttons inside.
128//!
129//! ```
130//! # use zng::prelude::*;
131//! # fn example() {
132//! let selected_item = var(1_i32);
133//! # let _ =
134//! Stack! {
135//!     toggle::style_fn = style_fn!(|_| toggle::RadioStyle!());
136//!     toggle::selector = toggle::Selector::single(selected_item.clone());
137//!     // ..
138//! }
139//! # ; }
140//! ```
141//!
142//! ## Combo
143//!
144//! The [`ComboStyle!`](struct@ComboStyle) together with the [`checked_popup`](struct@Toggle#method.checked_popup) property can be used
145//! to declare a combo box, that is a toggle for a drop down that contains another toggle selector context that selects a value.
146//!
147//! Note that the `checked_popup` setups the `checked` state, you cannot set one of the other checked properties in the same
148//! widget.
149//!
150//! The example below declares a combo box with a `TextInput!` content, users can type a custom option or open the popup and pick
151//! an option. Note that this also restyles `Toggle!` inside the popup to look like a menu item.
152//!
153//! ```
154//! use zng::prelude::*;
155//! # fn example() {
156//!
157//! let txt = var(Txt::from_static("Combo"));
158//! let options = ["Combo", "Congo", "Pombo"];
159//! # let _ =
160//! Toggle! {
161//!     child = TextInput! {
162//!         txt = txt.clone();
163//!         gesture::on_click = hn!(|a| a.propagation().stop());
164//!     };
165//!     style_fn = toggle::ComboStyle!();
166//!
167//!     checked_popup = wgt_fn!(|_| popup::Popup! {
168//!         id = "popup";
169//!         child = Stack! {
170//!             toggle::selector = toggle::Selector::single(txt.clone());
171//!             direction = StackDirection::top_to_bottom();
172//!             children = options.into_iter().map(|o| {
173//!                 Toggle! {
174//!                     child = Text!(o);
175//!                     value::<Txt> = o;
176//!                 }
177//!             });
178//!         };
179//!     });
180//! }
181//! # ; }
182//! ```
183//!
184//! # Full API
185//!
186//! See [`zng_wgt_toggle`] for the full widget API.
187
188pub use zng_wgt_toggle::{
189    CheckStyle, ComboStyle, DefaultStyle, IS_CHECKED_VAR, LightStyle, RadioStyle, Selector, SelectorError, SelectorImpl, SwitchStyle,
190    Toggle, check_style_fn, combo_style_fn, deselect_on_deinit, deselect_on_new, is_checked, light_style_fn, radio_style_fn,
191    scroll_on_select, select_on_init, select_on_new, selector, style_fn, switch_style_fn, tristate,
192};
193
194/// Toggle commands.
195pub mod cmd {
196    pub use zng_wgt_toggle::cmd::{SELECT_CMD, SelectOp, TOGGLE_CMD};
197}