bevy_ui_builders/number_input/
builder.rs1use bevy::prelude::*;
4use super::types::*;
5use crate::text_input::{TextInputBuilder, InputFilter};
6
7pub struct NumberInputBuilder {
23 min: Option<f32>,
24 max: Option<f32>,
25 step: f32,
26 default_value: Option<f32>,
27 width: Val,
28 placeholder: Option<String>,
29}
30
31impl NumberInputBuilder {
32 pub fn new() -> Self {
34 Self {
35 min: None,
36 max: None,
37 step: 1.0,
38 default_value: None,
39 width: Val::Px(crate::styles::dimensions::INPUT_WIDTH_DEFAULT),
40 placeholder: None,
41 }
42 }
43
44 pub fn min(mut self, min: f32) -> Self {
46 self.min = Some(min);
47 self
48 }
49
50 pub fn max(mut self, max: f32) -> Self {
52 self.max = Some(max);
53 self
54 }
55
56 pub fn step(mut self, step: f32) -> Self {
58 self.step = step;
59 self
60 }
61
62 pub fn default_value(mut self, value: f32) -> Self {
64 self.default_value = Some(value);
65 self
66 }
67
68 pub fn width(mut self, width: Val) -> Self {
70 self.width = width;
71 self
72 }
73
74 pub fn with_placeholder(mut self, placeholder: impl Into<String>) -> Self {
76 self.placeholder = Some(placeholder.into());
77 self
78 }
79
80 pub fn build(self, parent: &mut ChildSpawnerCommands) -> Entity {
82 let config = NumberInputConfig {
83 min: self.min,
84 max: self.max,
85 step: self.step,
86 };
87
88 let initial_value = if let Some(value) = self.default_value {
90 Some(config.clamp_value(value).to_string())
91 } else {
92 None
93 };
94
95 let hint = match (self.min, self.max) {
97 (Some(min), Some(max)) => Some(format!("Range: {}-{}", min, max)),
98 (Some(min), None) => Some(format!("Min: {}", min)),
99 (None, Some(max)) => Some(format!("Max: {}", max)),
100 (None, None) => None,
101 };
102
103 let mut text_input = TextInputBuilder::new()
105 .with_width(self.width)
106 .with_filter(InputFilter::Decimal);
107
108 if let Some(placeholder) = self.placeholder {
110 text_input = text_input.with_placeholder(&placeholder);
111 } else if let Some(hint_text) = hint {
112 text_input = text_input.with_placeholder(&hint_text);
113 }
114
115 if let Some(value_str) = initial_value {
117 text_input = text_input.with_value(&value_str);
118 }
119
120 if self.min.is_some() || self.max.is_some() {
122 let min = self.min.unwrap_or(f32::MIN);
123 let max = self.max.unwrap_or(f32::MAX);
124 text_input = text_input.with_validation(vec![
125 crate::ValidationRule::Range { min, max }
126 ]);
127 }
128
129 let entity = text_input.build(parent);
131
132 parent.commands().entity(entity).insert((
133 NumberInput,
134 config,
135 ));
136
137 entity
138 }
139}
140
141impl Default for NumberInputBuilder {
142 fn default() -> Self {
143 Self::new()
144 }
145}