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//! # let _scope = APP.defaults();
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//! # let _scope = APP.defaults();
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//! # let _scope = APP.defaults();
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 = (1..=10_i32).map(|i| {
62//!         Toggle! {
63//!             child = Text!("Item {i}");
64//!             value::<i32> = i;
65//!         }
66//!         .boxed()
67//!     }).collect::<Vec<_>>();
68//! }
69//! # ;
70//! ```
71//!
72//! Regardless of how the checked state of a toggle is defined the [`IS_CHECKED_VAR`] variable and [`is_checked`](fn@is_checked) property
73//! can be used to track the checked state of the widget. The example below defines a toggle that changes background color to green
74//! when it is in the `Some(true)` state.
75//!
76//! ```
77//! # use zng::prelude::*;
78//! # let _scope = APP.defaults();
79//! # let _ =
80//! Toggle! {
81//!     checked = var(false);
82//!     // checked_opt = var(Some(false));
83//!     // value<i32> = 42;
84//!
85//!     widget::background_color = colors::RED;
86//!     when *#is_checked {
87//!         widget::background_color = colors::GREEN;
88//!     }
89//! }
90//! # ;
91//! ```
92//!
93//! # Styles
94//!
95//! Toggle is a versatile widget, it can be styled to represent check boxes, switches, radio buttons and combo boxes.
96//!
97//! ## Check & Switch
98//!
99//! The [`CheckStyle!`](struct@CheckStyle) changes the toggle into a check box. The [`SwitchStyle!`](struct@SwitchStyle)
100//! changes the toggle into an on/off switch.
101//!
102//! ```
103//! use zng::prelude::*;
104//! # let _scope = APP.defaults();
105//!
106//! # let _ =
107//! Toggle! {
108//!     child = Text!(toggle::IS_CHECKED_VAR.map(|&s| match s {
109//!         Some(true) => Txt::from("checked text"),
110//!         Some(false) => Txt::from("unchecked text"),
111//!         None => Txt::from(""),
112//!     }));
113//!     checked = var(false);
114//!     style_fn = toggle::SwitchStyle!();
115//! }
116//! # ;
117//! ```
118//!
119//! The example above declares a toggle switch that changes the text depending on the state.
120//!
121//! ## Radio
122//!
123//! The [`RadioStyle!`](struct@RadioStyle) can be used in `value` toggle areas. The example below
124//! declares a stack that is a selector context and sets the toggle style for all toggle buttons inside.
125//!
126//! ```
127//! # use zng::prelude::*;
128//! # let _scope = APP.defaults();
129//! let selected_item = var(1_i32);
130//! # let _ =
131//! Stack! {
132//!     toggle::style_fn = style_fn!(|_| toggle::RadioStyle!());
133//!     toggle::selector = toggle::Selector::single(selected_item.clone());
134//!     // ..
135//! }
136//! # ;
137//! ```
138//!
139//! ## Combo
140//!
141//! The [`ComboStyle!`](struct@ComboStyle) together with the [`checked_popup`](struct@Toggle#method.checked_popup) property can be used
142//! to declare a combo box, that is a toggle for a drop down that contains another toggle selector context that selects a value.
143//!
144//! Note that the `checked_popup` setups the `checked` state, you cannot set one of the other checked properties in the same
145//! widget.
146//!
147//! The example below declares a combo box with a `TextInput!` content, users can type a custom option or open the popup and pick
148//! an option. Note that the `ComboStyle!` also restyles `Toggle!` inside the popup to look like a menu item.
149//!
150//! ```
151//! use zng::prelude::*;
152//! # let _scope = APP.defaults();
153//!
154//! let txt = var(Txt::from_static("Combo"));
155//! let options = ["Combo", "Congo", "Pombo"];
156//! # let _ =
157//! Toggle! {
158//!     child = TextInput! {
159//!         txt = txt.clone();
160//!         gesture::on_click = hn!(|a: &gesture::ClickArgs| a.propagation().stop());
161//!     };
162//!     style_fn = toggle::ComboStyle!();
163//!
164//!     checked_popup = wgt_fn!(|_| popup::Popup! {
165//!         id = "popup";
166//!         child = Stack! {
167//!             toggle::selector = toggle::Selector::single(txt.clone());
168//!             direction = StackDirection::top_to_bottom();
169//!             children = options.into_iter().map(|o| Toggle! {
170//!                 child = Text!(o);
171//!                 value::<Txt> = o;
172//!             })
173//!             .collect::<UiVec>();
174//!         };
175//!     })
176//! }
177//! # ;
178//! ```
179//!
180//! # Full API
181//!
182//! See [`zng_wgt_toggle`] for the full widget API.
183
184pub use zng_wgt_toggle::{
185    CheckStyle, ComboStyle, DefaultStyle, IS_CHECKED_VAR, LightStyle, RadioStyle, Selector, SelectorError, SelectorImpl, SwitchStyle,
186    Toggle, check_spacing, combo_spacing, deselect_on_deinit, deselect_on_new, is_checked, radio_spacing, scroll_on_select, select_on_init,
187    select_on_new, selector, style_fn, switch_spacing, tristate,
188};
189
190/// Toggle commands.
191pub mod cmd {
192    pub use zng_wgt_toggle::cmd::{SELECT_CMD, SelectOp, TOGGLE_CMD};
193}