GPUI Box GitHub

Components / display

Heatmap builder

A labelled grid of intensity cells.

A builder is RenderOnce. Construct and mount it in one expression.

use gpui_kit::display::heatmap::Heatmap;

Reviewed in heatmap.

Construct
new(ident: impl Into<Ident>, label: impl Into<SharedString>) -> Self
Options

Chain onto the value.

tint(tint: gpui::Hsla) -> Self
rows(rows: impl IntoIterator<Item = impl Into<HeatAxis>>) -> Self
columns(columns: impl IntoIterator<Item = impl Into<HeatAxis>>) -> Self
cells(cells: impl IntoIterator<Item = HeatCell>) -> Self
state(state: HeatmapState) -> Self
Example · heatmap
fn heatmap(_window: &mut Window, cx: &mut App) -> AnyElement {
    let theme = cx.theme().clone();
    // A quarter of weekdays, which is the shape this component is actually
    // asked for. Four columns of five said nothing about how the grid reads
    // once it carries a period somebody would look at.
    let days = ["Mon", "Tue", "Wed", "Thu", "Fri"];
    // Week-starting dates. Each column is joined on by its own key and prints
    // the day of the month, which is what fits over a cell; the month it came
    // from is the group header over the run of columns that share it, because
    // `3 10 17 24` three times over names nothing on its own.
    let starts = [6, 13, 20, 27, 3, 10, 17, 24, 3, 10, 17, 24];
    let month_of = |column: usize| ["January", "February", "March"][column / 4];
    let weeks: Vec<HeatAxis> = starts
        .iter()
        .enumerate()
        .map(|(column, day)| {
            HeatAxis::new(format!("w{column}"), day.to_string()).group(month_of(column))
        })
        .collect();
    let mut cells = Vec::new();
    for (row, day) in days.iter().enumerate() {
        for (column, week) in weeks.iter().enumerate() {
            let month = month_of(column);
            let mut cell = HeatCell::new(format!("{day}-{}", week.id), *day, week.id.clone())
                .label(format!("{day}, {month} {}", week.label));
            // Deterministic, and holed in two places so the difference between
            // "nothing was measured" and "zero was measured" has somewhere to
            // show itself.
            let sample = (row * 7 + column * 3 + (column * column) % 5) % 11;
            if sample != 4 && sample != 9 {
                let level = (sample % 5) as u8;
                cell = cell.level(level).value(format!("{level} runs"));
            }
            cells.push(cell);
        }
    }
    stack(&theme)
        .w(px(560.0))
        .child(caption(
            &theme,
            "January to March, by weekday: five intensity steps, and a missing \
             cell is not a measured zero",
        ))
        .child(
            Heatmap::new("scene.heatmap.ready", "Fixture activity")
                .rows(days)
                // The ramp is neutral until a caller says whose quantity it
                // is. This matrix is the run activity the rest of the frame
                // is already reading in the accent, so it hands that over.
                .tint(theme.colors.accent)
                .columns(weeks.clone())
                .cells(cells),
        )
        .child(
            Heatmap::new("scene.heatmap.loading", "Fixture activity").state(HeatmapState::Loading),
        )
        .child(caption(&theme, "Nothing measured in the period at all"))
        .child(Heatmap::new("scene.heatmap.empty", "Fixture activity").state(HeatmapState::Empty))
        .child(
            Heatmap::new("scene.heatmap.error", "Fixture activity")
                .state(HeatmapState::Error("The activity request failed.".into())),
        )
        .into_any_element()
}

Source: crates/gpui-kit/src/display/heatmap.rs