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()
}