tessera_ui_basic_components/
progress.rs1use derive_builder::Builder;
7use tessera_ui::{Color, ComputedData, Constraint, DimensionValue, Dp, Px, PxPosition, tessera};
8
9use crate::{
10 shape_def::Shape,
11 surface::{SurfaceArgsBuilder, surface},
12};
13
14#[derive(Builder, Clone, Debug)]
16#[builder(pattern = "owned")]
17pub struct ProgressArgs {
18 #[builder(default = "0.0")]
20 pub value: f32,
21
22 #[builder(default = "Dp(200.0)")]
24 pub width: Dp,
25
26 #[builder(default = "Dp(8.0)")]
28 pub height: Dp,
29
30 #[builder(default = "crate::material_color::global_material_scheme().primary")]
32 pub progress_color: Color,
33
34 #[builder(default = "crate::material_color::global_material_scheme().surface_variant")]
36 pub track_color: Color,
37}
38
39#[tessera]
65pub fn progress(args: impl Into<ProgressArgs>) {
66 let args: ProgressArgs = args.into();
67
68 surface(
70 SurfaceArgsBuilder::default()
71 .style(args.track_color.into())
72 .shape(Shape::capsule())
73 .width(DimensionValue::Fill {
74 min: None,
75 max: None,
76 })
77 .height(DimensionValue::Fill {
78 min: None,
79 max: None,
80 })
81 .build()
82 .expect("builder construction failed"),
83 None,
84 || {},
85 );
86
87 surface(
89 SurfaceArgsBuilder::default()
90 .style(args.progress_color.into())
91 .shape(Shape::capsule())
92 .width(DimensionValue::Fill {
93 min: None,
94 max: None,
95 })
96 .height(DimensionValue::Fill {
97 min: None,
98 max: None,
99 })
100 .build()
101 .expect("builder construction failed"),
102 None,
103 || {},
104 );
105
106 measure(Box::new(move |input| {
107 let self_width = args.width.to_px();
108 let self_height = args.height.to_px();
109
110 let track_id = input.children_ids[0];
111 let progress_id = input.children_ids[1];
112
113 let track_constraint = Constraint::new(
115 DimensionValue::Fixed(self_width),
116 DimensionValue::Fixed(self_height),
117 );
118 input.measure_child(track_id, &track_constraint)?;
119 input.place_child(track_id, PxPosition::new(Px(0), Px(0)));
120
121 let clamped_value = args.value.clamp(0.0, 1.0);
123 let progress_width = Px::saturating_from_f32(self_width.to_f32() * clamped_value);
124 let progress_constraint = Constraint::new(
125 DimensionValue::Fixed(progress_width),
126 DimensionValue::Fixed(self_height),
127 );
128 input.measure_child(progress_id, &progress_constraint)?;
129 input.place_child(progress_id, PxPosition::new(Px(0), Px(0)));
130
131 Ok(ComputedData {
133 width: self_width,
134 height: self_height,
135 })
136 }));
137}