zng/
style.rs

1//! Style mixin and other types.
2//!
3//! A [`Style!`](struct@Style) is an special widget that represents a set of properties that are dynamically applied to
4//! another styleable widget. Styleable widgets inherit from [`StyleMix<P>`](struct@StyleMix) and provide a contextual
5//! `style_fn` property that sets the widget style.
6//!
7//! Styles extend the contextual style by default, only replacing the intersection of properties.
8//! The special [`replace`](struct@Style#method.replace) property can be set on a style to fully replace the contextual style.
9//!
10//! The example below demonstrates multiple contexts setting style for buttons.
11//!
12//! ```
13//! use zng::prelude::*;
14//! # let _app = APP.defaults();
15//!
16//! # let _ =
17//! Stack! {
18//!     direction = StackDirection::top_to_bottom();
19//!     spacing = 5;
20//!
21//!     zng::button::style_fn = Style! {
22//!         // override the default background_color for all buttons in the Stack.
23//!         // note that this does not override the hovered/pressed background.
24//!         widget::background_color = colors::BLUE;
25//!     };
26//!
27//!     children = ui_vec![
28//!         // these buttons have the default style with blue background.
29//!         Button! {
30//!             child = Text!("Default+BLUE");
31//!         },
32//!         Button! {
33//!             child = Text!("Default+BLUE");
34//!         },
35//!         Stack! {
36//!             direction = StackDirection::top_to_bottom();
37//!             spacing = 5;
38//!
39//!             zng::button::style_fn = Style! {
40//!                 // override the default border for all buttons in the Stack.
41//!                 widget::border = 2, colors::GREEN;
42//!             };
43//!
44//!             children = ui_vec![
45//!                 // these buttons have the default style, with blue background and green border.
46//!                 Button! {
47//!                     child = Text!("Default+BLUE+GREEN");
48//!                 },
49//!                 Button! {
50//!                     child = Text!("Default+BLUE+GREEN");
51//!                 },
52//!                 Stack! {
53//!                     direction = StackDirection::top_to_bottom();
54//!                     spacing = 5;
55//!
56//!                     zng::button::style_fn = Style! {
57//!                         // override the context style background_color in the Stack.
58//!                         widget::background_color = colors::RED;
59//!                     };
60//!
61//!                     children = ui_vec![
62//!                         // these buttons have the default style, with green border and red background.
63//!                         Button! {
64//!                             child = Text!("Default+GREEN+RED");
65//!                         },
66//!                         Button! {
67//!                             child = Text!("Default+GREEN+RED");
68//!                         },
69//!                         // this button ignores the contextual style by setting the `style_fn` to a style
70//!                         // that is `replace=true`.
71//!                         Button! {
72//!                             child = Text!("Default");
73//!                             style_fn = zng::button::DefaultStyle!();
74//!                         },
75//!                     ];
76//!                 },
77//!             ];
78//!         },
79//!         Stack! {
80//!             direction = StackDirection::top_to_bottom();
81//!             spacing = 5;
82//!
83//!             zng::button::style_fn = Style! {
84//!                 // replace the default style with this one.
85//!                 replace = true;
86//!                 widget::background_color = colors::RED;
87//!             };
88//!
89//!             // these buttons only have the red background.
90//!             children = ui_vec![
91//!                 Button! {
92//!                     child = Text!("RED");
93//!                 },
94//!                 Button! {
95//!                     child = Text!("RED");
96//!                 },
97//!             ];
98//!         }
99//!     ];
100//! }
101//! # ;
102//! ```
103//!
104//! # Named Styles
105//!
106//! Some widgets provide alternate styles that are also contextual. The example below demonstrates a button using
107//! a named style being affected by properties set for that particular style name in context.
108//!
109//! ```
110//! use zng::prelude::*;
111//! # let _app = APP.defaults();
112//!
113//! # let _ =
114//! Stack! {
115//!     direction = StackDirection::top_to_bottom();
116//!     spacing = 5;
117//!
118//!     zng::button::light_style_fn = Style! {
119//!         // override the background color of only buttons in the Stack using the `LightStyle!`.
120//!         widget::background_color = colors::BLUE;
121//!     };
122//!     zng::button::style_fn = Style! {
123//!         // override the default border for all buttons in the Stack.
124//!         widget::border = 2, colors::GREEN;
125//!     };
126//!
127//!     children = ui_vec![
128//!         // This button is affected by the contextual light and default styles.
129//!         Button! {
130//!             child = Text!("BLUE+GREEN");
131//!             style_fn = zng::button::LightStyle!();
132//!         },
133//!         // This button is only affected by the contextual default style.
134//!         Button! {
135//!             child = Text!("Normal+GREEN");
136//!         },
137//!     ];
138//! }
139//! # ;
140//! ```
141//!
142//! Named styles accumulate context the same way the widget default style does. When applied the widget properties are
143//! set/replaced in this order:
144//!
145//! 1 - The default properties set on the widget declaration.
146//! 2 - The default style and any extension/replacement style set for the default style using `style_fn` in a parent widget.
147//! 3 - The named style set using `style_fn` on the widget and any extension/replacement style set for the named style property in a parent widget.
148//! 4 - The properties set on the widget instance.
149//!
150//! Note that on the target widget instance only the `style_fn` property is used, the named style property is standalone and for use in parent widgets.
151//!
152//! Named styles are ideal for cases where an widget can have a distinct appearance without changing its behavior. For example instead of a
153//! *CheckBox!* widget the `Toggle!` widget provides a `toggle::{CheckStyle, check_style_fn}`. Theme implementers can restyle *check-boxes* just
154//! the same, and widget users don't need to change the widget type just to use a different appearance.
155//!
156//! # Shared Styles
157//!
158//! Style instances can be set directly on `style_fn` properties, but if the style is used by more then one widget property values
159//! that can't be cloned will only appear on the last widget to use the style. The [`style_fn!`] macro can be used to declare a
160//! closure that instantiates the style for each usage. The property values that can't be cloned are `impl IntoUiNode`.
161//!
162//! The example below demonstrates this issue:
163//!
164//! ```
165//! use zng::prelude::*;
166//! # fn example() {
167//!
168//! # let _ =
169//! Stack! {
170//!     direction = StackDirection::top_to_bottom();
171//!     spacing = 5;
172//!     widget::parallel = false; // init buttons sequentially
173//!
174//!     zng::button::style_fn = Style! {
175//!         // background is `impl IntoUiNode` that can't be cloned. Nodes
176//!         // are moved to the last place that requests it.
177//!         widget::background = zng::color::flood(colors::AZURE);
178//!     };
179//!     children = ui_vec![
180//!         Button! { child = Text!("Default") },
181//!         // the last button to init takes the background node.
182//!         Button! { child = Text!("Default+AZURE") },
183//!     ];
184//! }
185//! # ; }
186//! ```
187//!
188//! Using a closure to set fixes the issue:
189//!
190//! ```
191//! # use zng::prelude::*;
192//! # fn example() {
193//! #
194//! # let _ =
195//! # Stack! {
196//! zng::button::style_fn = style_fn!(|_| Style! {
197//!     widget::background = zng::color::flood(colors::AZURE);
198//! });
199//! # }
200//! # ; }
201
202pub use zng_wgt_style::{Style, StyleArgs, StyleBuilder, StyleFn, StyleMix, impl_named_style_fn, impl_style_fn, style_fn};