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