guise/feedback/
ringprogress.rs1use gpui::prelude::*;
8use gpui::{div, px, relative, App, FontWeight, IntoElement, SharedString, Window};
9
10use crate::devtools::Probed;
11use crate::theme::{theme, ColorName};
12
13#[derive(IntoElement)]
15pub struct RingProgress {
16 value: f32,
17 size: f32,
18 color: ColorName,
19 label: Option<SharedString>,
20}
21
22impl RingProgress {
23 pub fn new(value: f32) -> Self {
24 RingProgress {
25 value: value.clamp(0.0, 100.0),
26 size: 80.0,
27 color: ColorName::Blue,
28 label: None,
29 }
30 }
31
32 pub fn size(mut self, size: f32) -> Self {
34 self.size = size;
35 self
36 }
37
38 pub fn color(mut self, color: ColorName) -> Self {
39 self.color = color;
40 self
41 }
42
43 pub fn label(mut self, label: impl Into<SharedString>) -> Self {
45 self.label = Some(label.into());
46 self
47 }
48}
49
50impl RenderOnce for RingProgress {
51 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
52 let t = theme(cx);
53 let accent = t.color(self.color, t.primary_shade()).alpha(0.85);
54 let track = if t.scheme.is_dark() {
55 t.color(ColorName::Dark, 4)
56 } else {
57 t.color(ColorName::Gray, 2)
58 }
59 .hsla();
60 let text = t.text().hsla();
61 let frac = (self.value / 100.0).clamp(0.0, 1.0);
62 let label = self
63 .label
64 .unwrap_or_else(|| SharedString::from(format!("{}%", self.value.round() as i64)));
65
66 div()
67 .relative()
68 .w(px(self.size))
69 .h(px(self.size))
70 .rounded(px(self.size / 2.0))
71 .overflow_hidden()
72 .bg(track)
73 .flex()
74 .items_center()
75 .justify_center()
76 .child(
78 div()
79 .absolute()
80 .bottom(px(0.0))
81 .left(px(0.0))
82 .right(px(0.0))
83 .h(relative(frac))
84 .bg(accent),
85 )
86 .child(
88 div()
89 .font_weight(FontWeight::SEMIBOLD)
90 .text_size(px(self.size * 0.22))
91 .text_color(text)
92 .child(label),
93 )
94 .probe("RingProgress")
95 }
96}