herogpui_components/
meter.rs1use gpui::{App, IntoElement, Pixels, RenderOnce, SharedString, Window};
9use herogpui_core::{Color, Size};
10
11use crate::progress::ProgressBar;
12
13#[must_use = "a component does nothing until it is rendered: add it as a child or return it from `render`"]
16#[derive(IntoElement)]
17pub struct Meter {
18 id: gpui::ElementId,
19 value: f32,
20 min_value: f32,
21 max_value: f32,
22 size: Size,
23 color: Color,
24 label: Option<SharedString>,
25 value_label: Option<SharedString>,
26 value_content: Option<std::sync::Arc<dyn Fn(f32, &str) -> gpui::AnyElement + 'static>>,
29 show_value: bool,
30 format: Option<herogpui_core::NumberFormat>,
32 radius: Option<Pixels>,
35 sx: Option<Box<gpui::StyleRefinement>>,
37}
38
39impl Meter {
40 pub fn value(mut self, value: f32) -> Self {
42 self.value = value;
43 self
44 }
45
46 pub fn value_content(
49 mut self,
50 render: impl Fn(f32, &str) -> gpui::AnyElement + 'static,
51 ) -> Self {
52 self.value_content = Some(std::sync::Arc::new(render));
53 self
54 }
55
56 pub fn new(id: impl Into<gpui::ElementId>, value: f32) -> Self {
58 Self {
59 id: id.into(),
60 value_content: None,
61 value,
62 min_value: 0.0,
63 max_value: 100.0,
64 size: Size::Md,
65 color: Color::Accent,
66 label: None,
67 value_label: None,
68 show_value: false,
69 format: None,
70 radius: None,
71 sx: None,
72 }
73 }
74
75 pub fn min_value(mut self, v: f32) -> Self {
77 self.min_value = v;
78 self
79 }
80
81 pub fn max_value(mut self, v: f32) -> Self {
83 self.max_value = v;
84 self
85 }
86
87 pub fn value_label(mut self, text: impl Into<SharedString>) -> Self {
89 self.value_label = Some(text.into());
90 self
91 }
92
93 pub fn format_options(mut self, format: herogpui_core::NumberFormat) -> Self {
95 self.format = Some(format);
96 self
97 }
98
99 pub fn radius(mut self, radius: impl Into<Pixels>) -> Self {
105 self.radius = Some(radius.into());
106 self
107 }
108
109 pub fn size(mut self, s: Size) -> Self {
111 self.size = s;
112 self
113 }
114
115 pub fn color(mut self, c: Color) -> Self {
117 self.color = c;
118 self
119 }
120
121 pub fn sx(mut self, style: impl FnOnce(gpui::Div) -> gpui::Div) -> Self {
128 crate::util::refine_sx(&mut self.sx, style);
129 self
130 }
131
132 pub fn label(mut self, l: impl Into<SharedString>) -> Self {
134 self.label = Some(l.into());
135 self
136 }
137
138 pub fn show_value(mut self, v: bool) -> Self {
140 self.show_value = v;
141 self
142 }
143}
144
145impl RenderOnce for Meter {
146 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
147 let mut p = ProgressBar::new(self.id)
150 .as_meter()
151 .value(self.value)
152 .min_value(self.min_value)
153 .max_value(self.max_value)
154 .size(self.size)
155 .color(self.color)
156 .show_value_label(self.show_value);
157 if let Some(format) = self.format.clone() {
158 p = p.format_options(format);
159 }
160 if let Some(render) = self.value_content {
161 p = p.value_content(move |percentage, text, _| render(percentage, text));
162 }
163 if let Some(vl) = self.value_label {
164 p = p.value_label(vl);
165 }
166 if let Some(l) = self.label {
167 p = p.label(l.to_string());
168 }
169 if let Some(radius) = self.radius {
172 p = p.radius(radius);
173 }
174 if let Some(sx) = self.sx {
177 p = p.sx_refinement(sx);
178 }
179 p.into_any_element()
180 }
181}
182
183crate::util::impl_component_styled!(Meter);