gpui_component/
progress.rs1use crate::{ActiveTheme, StyledExt};
2use gpui::{
3 div, prelude::FluentBuilder, px, relative, App, Hsla, IntoElement, ParentElement, RenderOnce,
4 StyleRefinement, Styled, Window,
5};
6
7#[derive(IntoElement)]
9pub struct Progress {
10 style: StyleRefinement,
11 color: Option<Hsla>,
12 value: f32,
13}
14
15impl Progress {
16 pub fn new() -> Self {
18 Progress {
19 value: Default::default(),
20 color: None,
21 style: StyleRefinement::default().h(px(8.)).rounded(px(4.)),
22 }
23 }
24
25 pub fn bg(mut self, color: impl Into<Hsla>) -> Self {
27 self.color = Some(color.into());
28 self
29 }
30
31 pub fn value(mut self, value: f32) -> Self {
35 self.value = value.clamp(0., 100.);
36 self
37 }
38}
39
40impl Styled for Progress {
41 fn style(&mut self) -> &mut StyleRefinement {
42 &mut self.style
43 }
44}
45
46impl RenderOnce for Progress {
47 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
48 let radius = self.style.corner_radii.clone();
49 let mut inner_style = StyleRefinement::default();
50 inner_style.corner_radii = radius;
51
52 let color = self.color.unwrap_or(cx.theme().progress_bar);
53
54 let relative_w = relative(match self.value {
55 v if v < 0. => 0.,
56 v if v > 100. => 1.,
57 v => v / 100.,
58 });
59
60 div()
61 .w_full()
62 .relative()
63 .rounded_full()
64 .refine_style(&self.style)
65 .bg(color.opacity(0.2))
66 .child(
67 div()
68 .absolute()
69 .top_0()
70 .left_0()
71 .h_full()
72 .w(relative_w)
73 .bg(color)
74 .map(|this| match self.value {
75 v if v >= 100. => this.refine_style(&inner_style),
76 _ => this.refine_style(&inner_style).rounded_r_none(),
77 }),
78 )
79 }
80}