use documented::Documented;use gpui::{Hsla, point}; use crate::components::Label;use crate::prelude::*; /// A progress bar is a horizontal bar that communicates the status of a process.////// A progress bar should not be used to represent indeterminate progress.#[derive(IntoElement, RegisterComponent, Documented)]pub struct ProgressBar { id: ElementId, value: f32, max_value: f32, bg_color: Hsla, over_color: Hsla, fg_color: Hsla,} impl ProgressBar { pub fn new(id: impl Into<ElementId>, value: f32, max_value: f32, cx: &App) -> Self { Self { id: id.into(), value, max_value, bg_color: cx.theme().colors().background, over_color: cx.theme().status().error, fg_color: cx.theme().status().info, } } /// Sets the current value of the progress bar. pub fn value(mut self, value: f32) -> Self { self.value = value; self } /// Sets the maximum value of the progress bar. pub fn max_value(mut self, max_value: f32) -> Self { self.max_value = max_value; self } /// Sets the background color of the progress bar. pub fn bg_color(mut self, color: Hsla) -> Self { self.bg_color = color; self } /// Sets the foreground color of the progress bar. pub fn fg_color(mut self, color: Hsla) -> Self { self.fg_color = color; self } /// Sets the over limit color of the progress bar. pub fn over_color(mut self, color: Hsla) -> Self { self.over_color = color; self }} impl RenderOnce for ProgressBar { fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement { let fill_width = (self.value / self.max_value).clamp(0.02, 1.0); div() .id(self.id.clone()) .w_full() .h_2() .p_0p5() .rounded_full() .bg(self.bg_color) .shadow(vec![gpui::BoxShadow { color: gpui::black().opacity(0.08), offset: point(px(0.), px(1.)), blur_radius: px(0.), spread_radius: px(0.), }]) .child( div() .h_full() .rounded_full() .when(self.value > self.max_value, |div| div.bg(self.over_color)) .when(self.value <= self.max_value, |div| div.bg(self.fg_color)) .w(relative(fill_width)), ) }} impl Component for ProgressBar { fn scope() -> ComponentScope { ComponentScope::Status } fn description() -> Option<&'static str> { Some(Self::DOCS) } fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> { let max_value = 180.0; let container = || v_flex().w_full().gap_1(); Some( example_group(vec![single_example( "Examples", v_flex() .w_full() .gap_2() .child( container() .child( h_flex() .justify_between() .child(Label::new("0%")) .child(Label::new("Empty")), ) .child(ProgressBar::new("empty", 0.0, max_value, cx)), ) .child( container() .child( h_flex() .justify_between() .child(Label::new("38%")) .child(Label::new("Partial")), ) .child(ProgressBar::new("partial", max_value * 0.35, max_value, cx)), ) .child( container() .child( h_flex() .justify_between() .child(Label::new("100%")) .child(Label::new("Complete")), ) .child(ProgressBar::new("filled", max_value, max_value, cx)), ) .into_any_element(), )]) .into_any_element(), ) }}
use documented::Documented;
use gpui::{Hsla, point};
use crate::components::Label;
use crate::prelude::*;
/// A progress bar is a horizontal bar that communicates the status of a process.
///
/// A progress bar should not be used to represent indeterminate progress.
#[derive(IntoElement, RegisterComponent, Documented)]
pub struct ProgressBar {
id: ElementId,
value: f32,
max_value: f32,
bg_color: Hsla,
over_color: Hsla,
fg_color: Hsla,
}
impl ProgressBar {
pub fn new(id: impl Into<ElementId>, value: f32, max_value: f32, cx: &App) -> Self {
Self {
id: id.into(),
value,
max_value,
bg_color: cx.theme().colors().background,
over_color: cx.theme().status().error,
fg_color: cx.theme().status().info,
}
}
/// Sets the current value of the progress bar.
pub fn value(mut self, value: f32) -> Self {
self.value = value;
self
}
/// Sets the maximum value of the progress bar.
pub fn max_value(mut self, max_value: f32) -> Self {
self.max_value = max_value;
self
}
/// Sets the background color of the progress bar.
pub fn bg_color(mut self, color: Hsla) -> Self {
self.bg_color = color;
self
}
/// Sets the foreground color of the progress bar.
pub fn fg_color(mut self, color: Hsla) -> Self {
self.fg_color = color;
self
}
/// Sets the over limit color of the progress bar.
pub fn over_color(mut self, color: Hsla) -> Self {
self.over_color = color;
self
}
}
impl RenderOnce for ProgressBar {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let fill_width = (self.value / self.max_value).clamp(0.02, 1.0);
div()
.id(self.id.clone())
.w_full()
.h_2()
.p_0p5()
.rounded_full()
.bg(self.bg_color)
.shadow(vec![gpui::BoxShadow {
color: gpui::black().opacity(0.08),
offset: point(px(0.), px(1.)),
blur_radius: px(0.),
spread_radius: px(0.),
}])
.child(
div()
.h_full()
.rounded_full()
.when(self.value > self.max_value, |div| div.bg(self.over_color))
.when(self.value <= self.max_value, |div| div.bg(self.fg_color))
.w(relative(fill_width)),
)
}
}
impl Component for ProgressBar {
fn scope() -> ComponentScope {
ComponentScope::Status
}
fn description() -> Option<&'static str> {
Some(Self::DOCS)
}
fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
let max_value = 180.0;
let container = || v_flex().w_full().gap_1();
Some(
example_group(vec![single_example(
"Examples",
v_flex()
.w_full()
.gap_2()
.child(
container()
.child(
h_flex()
.justify_between()
.child(Label::new("0%"))
.child(Label::new("Empty")),
)
.child(ProgressBar::new("empty", 0.0, max_value, cx)),
)
.child(
container()
.child(
h_flex()
.justify_between()
.child(Label::new("38%"))
.child(Label::new("Partial")),
)
.child(ProgressBar::new("partial", max_value * 0.35, max_value, cx)),
)
.child(
container()
.child(
h_flex()
.justify_between()
.child(Label::new("100%"))
.child(Label::new("Complete")),
)
.child(ProgressBar::new("filled", max_value, max_value, cx)),
)
.into_any_element(),
)])
.into_any_element(),
)
}
}