1use std::f32::consts::PI;
4
5use bevy::{
6 feathers::{
7 controls::*,
8 dark_theme::create_dark_theme,
9 display::label,
10 theme::{ThemeBackgroundColor, UiTheme},
11 tokens, FeathersPlugins,
12 },
13 input_focus::tab_navigation::TabGroup,
14 prelude::*,
15 ui::InteractionDisabled,
16 ui_widgets::ValueChange,
17};
18
19fn main() {
20 App::new()
21 .add_plugins((DefaultPlugins, FeathersPlugins))
22 .insert_resource(UiTheme(create_dark_theme()))
23 .add_systems(Startup, scene.spawn())
24 .run();
26}
27
28fn scene() -> impl SceneList {
29 bsn_list! {
30 Camera2d
31 --
32 @demo_root()
33 }
34}
35
36fn demo_root() -> impl Scene {
37 bsn! {
38 Node {
39 width: percent(100),
40 height: percent(100),
41 align_items: AlignItems::Start,
42 justify_content: JustifyContent::Start,
43 display: Display::Flex,
44 flex_direction: FlexDirection::Column,
45 flex_wrap: FlexWrap::Wrap,
46 padding: px(8),
47 row_gap: px(8),
48 }
49 TabGroup
50 ThemeBackgroundColor(tokens::WINDOW_BG)
51 Children[
52 @demo_field_f32("none (bare)", 1.0, bsn! {})
53 --
54 @demo_field_f32("soft limit", 2.0, bsn! {
55 SoftLimit(NumberInputRange::F32(0.0..=10.0))
56 })
57 --
58 @demo_field_f32("hard limit", 3.0, bsn! {
59 HardLimit(NumberInputRange::F32(-100.0..=100.0))
60 })
61 --
62 @demo_field_f32("soft + hard", 4.0, bsn! {
63 SoftLimit(NumberInputRange::F32(0.0..=10.0))
64 HardLimit(NumberInputRange::F32(-100.0..=100.0))
65 })
66 --
67 @demo_field_f32("precision(0)", 5.0, bsn! {
68 NumberInputPrecision(0)
69 })
70 --
71 @demo_field_f32("precision(2)", 6.0, bsn! {
72 NumberInputPrecision(2)
73 })
74 --
75 @demo_field_f32("precision(4)", 7.0, bsn! {
76 NumberInputPrecision(4)
77 })
78 --
79 @demo_field_f32("step(1.0)", 8.0, bsn! {
80 NumberInputStep(1.0f64)
81 })
82 --
83 @demo_field_f64("f64: soft limit", 1.0f64, bsn! {
84 SoftLimit(NumberInputRange::F64(0.0f64..=10.0f64))
85 })
86 --
87 @demo_field_f64("f64: soft limit + precision(2)", 1.0f64, bsn! {
88 SoftLimit(NumberInputRange::F64(0.0f64..=10.0f64))
89 NumberInputPrecision(2)
90 })
91 --
92 @demo_field_i32("i32: bare", 1, bsn! {})
93 --
94 @demo_field_i32("i32: soft limit", 1, bsn! {
95 SoftLimit(NumberInputRange::I32(0..=10))
96 })
97 --
98 @demo_field_f32_with_sigil("precision(2) + sigil", 6.0, bsn! {
99 NumberInputPrecision(2)
100 })
101 --
102 @demo_field_f32("soft limit + disabled", 2.0, bsn! {
103 InteractionDisabled
104 SoftLimit(NumberInputRange::F32(0.0..=10.0))
105 })
106 --
107 @demo_field_f32("hard limit + wrap", 0.0, bsn! {
108 HardLimit(NumberInputRange::F32(-180.0..=180.0))
109 NumberInputWrap::Wrap
110 })
111 --
112 @demo_field_f32("in meters", 2.0, bsn! {
113 NumberInputUnits::new(&LengthMeters)
114 })
115 --
116 @demo_field_f32("in seconds", 2.0, bsn! {
117 NumberInputUnits::new(&TimeSeconds)
118 })
119 --
120 @demo_field_f32("in degrees", PI, bsn! {
121 NumberInputUnits::new(&AngleDegrees)
122 })
123 ]
124 }
125}
126
127fn demo_field_f32(label_text: &str, value: f32, options: impl Scene) -> impl Scene {
128 bsn! {
129 Node {
130 display: Display::Flex,
131 flex_direction: FlexDirection::Column,
132 align_items: AlignItems::Start,
133 width: px(200),
134 row_gap: px(4),
135 }
136 Children [
137 @label(label_text)
138 --
139 Node {
140 display: Display::Flex,
141 flex_direction: FlexDirection::Row,
142 align_items: AlignItems::Center,
143 align_self: AlignSelf::Stretch,
144 justify_content: JustifyContent::SpaceBetween,
145 }
146 Children [
147 @FeathersNumberInput
148 NumberInputValue::F32(value)
149 @{options}
150 Node {
151 flex_grow: 1.0,
152 max_width: px(120),
153 }
154 on(
155 |value_change: On<ValueChange<f32>>, mut commands: Commands| {
156 commands.entity(value_change.event_target())
157 .insert(NumberInputValue::F32(value_change.value));
158 })
159 --
160 #Output
161 @label("-")
162 ]
163 ]
164 }
165}
166
167fn demo_field_f32_with_sigil(label_text: &str, value: f32, options: impl Scene) -> impl Scene {
168 bsn! {
169 Node {
170 display: Display::Flex,
171 flex_direction: FlexDirection::Column,
172 align_items: AlignItems::Start,
173 width: px(200),
174 }
175 Children [
176 @label(label_text)
177 --
178 Node {
179 display: Display::Flex,
180 flex_direction: FlexDirection::Row,
181 align_items: AlignItems::Center,
182 align_self: AlignSelf::Stretch,
183 justify_content: JustifyContent::SpaceBetween,
184 }
185 Children [
186 @FeathersNumberInput {
187 @sigil_color: tokens::TEXT_INPUT_X_AXIS,
188 @label_text: "X",
189 }
190 NumberInputValue::F32(value)
191 @{options}
192 Node {
193 flex_grow: 1.0,
194 max_width: px(120),
195 }
196 on(
197 |value_change: On<ValueChange<f32>>, mut commands: Commands| {
198 commands.entity(value_change.event_target())
199 .insert(NumberInputValue::F32(value_change.value));
200 })
201 --
202 #Output
203 @label("-")
204 ]
205 ]
206 }
207}
208
209fn demo_field_f64(label_text: &str, value: f64, options: impl Scene) -> impl Scene {
210 bsn! {
211 Node {
212 display: Display::Flex,
213 flex_direction: FlexDirection::Column,
214 align_items: AlignItems::Start,
215 width: px(200),
216 }
217 Children [
218 @label(label_text)
219 --
220 Node {
221 display: Display::Flex,
222 flex_direction: FlexDirection::Row,
223 align_items: AlignItems::Center,
224 align_self: AlignSelf::Stretch,
225 justify_content: JustifyContent::SpaceBetween,
226 }
227 Children [
228 @FeathersNumberInput
229 NumberInputValue::F64(value)
230 @{options}
231 Node {
232 flex_grow: 1.0,
233 max_width: px(120),
234 }
235 on(
236 |value_change: On<ValueChange<f64>>, mut commands: Commands| {
237 commands.entity(value_change.event_target())
238 .insert(NumberInputValue::F64(value_change.value));
239 })
240 --
241 #Output
242 @label("-")
243 ]
244 ]
245 }
246}
247
248fn demo_field_i32(label_text: &str, value: i32, options: impl Scene) -> impl Scene {
249 bsn! {
250 Node {
251 display: Display::Flex,
252 flex_direction: FlexDirection::Column,
253 align_items: AlignItems::Start,
254 width: px(200),
255 }
256 Children [
257 @label(label_text)
258 --
259 Node {
260 display: Display::Flex,
261 flex_direction: FlexDirection::Row,
262 align_items: AlignItems::Center,
263 align_self: AlignSelf::Stretch,
264 justify_content: JustifyContent::SpaceBetween,
265 }
266 Children [
267 @FeathersNumberInput
268 NumberInputValue::I32(value)
269 @{options}
270 Node {
271 flex_grow: 1.0,
272 max_width: px(120),
273 }
274 on(
275 |value_change: On<ValueChange<i32>>, mut commands: Commands| {
276 commands.entity(value_change.event_target())
277 .insert(NumberInputValue::I32(value_change.value));
278 })
279 --
280 #Output
281 @label("-")
282 ]
283 ]
284 }
285}