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 = "Color::new(0.2, 0.5, 0.8, 1.0)")]
32 pub progress_color: Color,
33
34 #[builder(default = "Color::new(0.8, 0.8, 0.8, 1.0)")]
36 pub track_color: Color,
37}
38
39#[tessera]
65pub fn progress(args: impl Into<ProgressArgs>) {
66 let args: ProgressArgs = args.into();
67 let radius_dp = Dp(args.height.0 / 2.0);
68
69 surface(
71 SurfaceArgsBuilder::default()
72 .style(args.track_color.into())
73 .shape({
74 Shape::RoundedRectangle {
75 top_left: radius_dp,
76 top_right: radius_dp,
77 bottom_right: radius_dp,
78 bottom_left: radius_dp,
79 g2_k_value: 2.0,
80 }
81 })
82 .width(DimensionValue::Fill {
83 min: None,
84 max: None,
85 })
86 .height(DimensionValue::Fill {
87 min: None,
88 max: None,
89 })
90 .build()
91 .unwrap(),
92 None,
93 || {},
94 );
95
96 surface(
98 SurfaceArgsBuilder::default()
99 .style(args.progress_color.into())
100 .shape({
101 Shape::RoundedRectangle {
102 top_left: radius_dp,
103 top_right: radius_dp,
104 bottom_right: radius_dp,
105 bottom_left: radius_dp,
106 g2_k_value: 2.0,
107 }
108 })
109 .width(DimensionValue::Fill {
110 min: None,
111 max: None,
112 })
113 .height(DimensionValue::Fill {
114 min: None,
115 max: None,
116 })
117 .build()
118 .unwrap(),
119 None,
120 || {},
121 );
122
123 measure(Box::new(move |input| {
124 let self_width = args.width.to_px();
125 let self_height = args.height.to_px();
126
127 let track_id = input.children_ids[0];
128 let progress_id = input.children_ids[1];
129
130 let track_constraint = Constraint::new(
132 DimensionValue::Fixed(self_width),
133 DimensionValue::Fixed(self_height),
134 );
135 input.measure_child(track_id, &track_constraint)?;
136 input.place_child(track_id, PxPosition::new(Px(0), Px(0)));
137
138 let clamped_value = args.value.clamp(0.0, 1.0);
140 let progress_width = Px::saturating_from_f32(self_width.to_f32() * clamped_value);
141 let progress_constraint = Constraint::new(
142 DimensionValue::Fixed(progress_width),
143 DimensionValue::Fixed(self_height),
144 );
145 input.measure_child(progress_id, &progress_constraint)?;
146 input.place_child(progress_id, PxPosition::new(Px(0), Px(0)));
147
148 Ok(ComputedData {
150 width: self_width,
151 height: self_height,
152 })
153 }));
154}