stormdl-gui 0.1.2

GPUI + Adabraka UI application
Documentation
use adabraka_ui::prelude::*;
use gpui::*;
use stormdl_core::{SegmentState, SegmentStatus};

pub struct SegmentedProgressBar {
    segments: Vec<SegmentState>,
    height: Pixels,
}

impl SegmentedProgressBar {
    pub fn new(segments: Vec<SegmentState>) -> Self {
        Self {
            segments,
            height: px(24.0),
        }
    }

    pub fn height(mut self, height: Pixels) -> Self {
        self.height = height;
        self
    }

    fn segment_color(status: SegmentStatus) -> Hsla {
        match status {
            SegmentStatus::Pending => hsla(0.0, 0.0, 0.29, 1.0),
            SegmentStatus::Active => hsla(0.58, 1.0, 0.65, 1.0),
            SegmentStatus::Complete => hsla(0.39, 0.74, 0.58, 1.0),
            SegmentStatus::Error => hsla(0.0, 0.84, 0.6, 1.0),
            SegmentStatus::Slow => hsla(0.12, 0.98, 0.56, 1.0),
        }
    }
}

impl RenderOnce for SegmentedProgressBar {
    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
        let theme = use_theme();

        if self.segments.is_empty() {
            return div()
                .w_full()
                .h(self.height)
                .rounded_sm()
                .bg(theme.tokens.muted)
                .into_any_element();
        }

        let total_len: u64 = self.segments.iter().map(|s| s.range.len()).sum();
        if total_len == 0 {
            return div()
                .w_full()
                .h(self.height)
                .rounded_sm()
                .bg(theme.tokens.primary)
                .into_any_element();
        }

        div()
            .w_full()
            .h(self.height)
            .rounded_sm()
            .overflow_hidden()
            .flex()
            .children(self.segments.iter().map(|segment| {
                let width_fraction = segment.range.len() as f32 / total_len as f32;
                let fill_fraction = segment.progress() as f32;

                div()
                    .flex_shrink_0()
                    .h_full()
                    .relative()
                    .w(relative(width_fraction))
                    .bg(theme.tokens.muted)
                    .child(
                        div()
                            .absolute()
                            .left_0()
                            .top_0()
                            .h_full()
                            .w(relative(fill_fraction))
                            .bg(Self::segment_color(segment.status)),
                    )
            }))
            .into_any_element()
    }
}