bevy_ui_builders/progress/
builder.rs

1//! ProgressBarBuilder implementation
2
3use bevy::prelude::*;
4use crate::{colors, dimensions};
5use super::types::*;
6
7/// Builder for creating progress bars with consistent styling
8pub struct ProgressBarBuilder {
9    value: f32,
10    style: ProgressBarStyle,
11    width: Val,
12    height: Option<f32>,
13    margin: UiRect,
14    track_color: Option<Color>,
15    fill_color: Option<Color>,
16    show_label: bool,
17    custom_label: Option<String>,
18    animated: bool,
19}
20
21impl ProgressBarBuilder {
22    pub fn new(value: f32) -> Self {
23        Self {
24            value: value.clamp(0.0, 1.0),
25            style: ProgressBarStyle::Default,
26            width: Val::Percent(100.0),
27            height: None,
28            margin: UiRect::all(Val::Px(0.0)),
29            track_color: None,
30            fill_color: None,
31            show_label: false,
32            custom_label: None,
33            animated: false,
34        }
35    }
36
37    pub fn style(mut self, style: ProgressBarStyle) -> Self {
38        self.style = style;
39        self
40    }
41
42    pub fn width(mut self, width: Val) -> Self {
43        self.width = width;
44        self
45    }
46
47    /// Override the height
48    pub fn height(mut self, height: Val) -> Self {
49        if let Val::Px(px) = height {
50            self.height = Some(px);
51        }
52        self
53    }
54
55    pub fn margin(mut self, margin: UiRect) -> Self {
56        self.margin = margin;
57        self
58    }
59
60    /// Override the track color
61    pub fn track_color(mut self, color: Color) -> Self {
62        self.track_color = Some(color);
63        self
64    }
65
66    /// Override the fill color
67    pub fn fill_color(mut self, color: Color) -> Self {
68        self.fill_color = Some(color);
69        self
70    }
71
72    /// Show a percentage label
73    pub fn with_label(mut self) -> Self {
74        self.show_label = true;
75        self
76    }
77
78    /// Show a custom label text instead of percentage
79    pub fn with_label_text(mut self, text: impl Into<String>) -> Self {
80        self.custom_label = Some(text.into());
81        self.show_label = true;
82        self
83    }
84
85    /// Enable animation
86    pub fn animated(mut self) -> Self {
87        self.animated = true;
88        self
89    }
90
91    pub fn build(self, parent: &mut ChildSpawnerCommands) -> Entity {
92        let height = Val::Px(self.height.unwrap_or_else(|| self.style.height()));
93        let track_color = self.track_color.unwrap_or_else(|| self.style.track_color());
94        let fill_color = self.fill_color.unwrap_or_else(|| self.style.fill_color());
95
96        parent
97            .spawn((
98                Node {
99                    width: self.width,
100                    flex_direction: FlexDirection::Column,
101                    margin: self.margin,
102                    ..default()
103                },
104                BackgroundColor(Color::NONE),
105            ))
106            .with_children(|container| {
107                // Progress bar track (background)
108                container
109                    .spawn((
110                        Node {
111                            width: Val::Percent(100.0),
112                            height,
113                            position_type: PositionType::Relative,
114                            overflow: Overflow::clip(),
115                            ..default()
116                        },
117                        BackgroundColor(track_color),
118                        BorderRadius::all(Val::Px(2.0)),
119                        ProgressBarTrack,
120                    ))
121                    .with_children(|track| {
122                        // Progress bar fill
123                        track.spawn((
124                            Node {
125                                width: Val::Percent(self.value * 100.0),
126                                height: Val::Percent(100.0),
127                                position_type: PositionType::Absolute,
128                                left: Val::Px(0.0),
129                                top: Val::Px(0.0),
130                                ..default()
131                            },
132                            BackgroundColor(fill_color),
133                            BorderRadius::all(Val::Px(2.0)),
134                            ProgressBarFill,
135                        ));
136                    });
137
138                // Optional label
139                if self.show_label {
140                    let label_text = self
141                        .custom_label
142                        .unwrap_or_else(|| format!("{}%", (self.value * 100.0) as i32));
143
144                    container
145                        .spawn((
146                            Node {
147                                margin: UiRect::top(Val::Px(4.0)),
148                                justify_content: JustifyContent::Center,
149                                ..default()
150                            },
151                            BackgroundColor(Color::NONE),
152                        ))
153                        .with_children(|label_container| {
154                            label_container.spawn((
155                                Text::new(label_text),
156                                TextFont {
157                                    font_size: dimensions::FONT_SIZE_SMALL,
158                                    ..default()
159                                },
160                                TextColor(colors::TEXT_MUTED),
161                                ProgressBarLabel,
162                            ));
163                        });
164                }
165            })
166            .insert(ProgressBar {
167                value: self.value,
168                style: self.style,
169                animated: self.animated,
170            })
171            .id()
172    }
173}
174
175/// Convenience function to create a progress bar builder
176pub fn progress(value: f32) -> ProgressBarBuilder {
177    ProgressBarBuilder::new(value)
178}