Files
Ely-GPUI-Components/src/generative/hardware.rs
T
ZacharyZhang-NY 81e73b79c1 Capture · Roots: roots drop w_full; hosts give the width
145 component roots drop w_full, the early returns included. Three
field rows keep it, Input, InputGroup and TagInput: stretched without
a width, taffy 0.9 laid the field's flex_1 share at no width in the
template picker at 280px, and the placeholder drew nothing. Container
keeps it, since mx_auto needs a width to fill.

Hosts that relied on a root's width now give it: MessageList boxes
each row at the list's width, the splash gives its bar the column's,
and test stages that mount a component as the window's root sit in a
size_full box. Tests hold a narrow row across the list and the splash
bar across its column; each goes red without its fix.

The gallery gains --narrow <px>, which lays each page in a padded
card at that width and shoots it without its script. The page
header wraps: the title takes the room and the theme switcher drops
below, where a long summary used to push it past the edge. A file
panel step waits for the panel to become key instead of a fixed
pause, which lost a race in a capture.
2026-09-28 13:07:22 -04:00

80 lines
2.6 KiB
Rust

use gpui::{
App, ElementId, IntoElement, ParentElement, RenderOnce, SharedString, Styled, Window, div,
prelude::*,
};
use crate::{
data_display::{Meter, Sparkline},
theme::ActiveTheme,
};
/// One part of the machine: its name, how full it is from 0 to 1, that in units, and its recent shares, oldest first.
#[derive(Clone, Debug, PartialEq)]
pub struct Reading {
pub name: SharedString,
pub share: f32,
pub detail: SharedString,
pub history: Vec<f32>,
}
/// The machine at work: a meter for each part, as GPU, its memory and the CPU, that turns amber then red as it fills, and beside it a line of its recent history.
#[derive(IntoElement)]
pub struct HardwareMonitor {
id: ElementId,
readings: Vec<Reading>,
}
impl HardwareMonitor {
pub fn new(id: impl Into<ElementId>, readings: impl IntoIterator<Item = Reading>) -> Self {
let readings: Vec<Reading> = readings.into_iter().collect();
for reading in &readings {
let within = |share: &f32| (0.0..=1.0).contains(share);
assert!(
within(&reading.share) && reading.history.iter().all(within),
"{} reads outside 0 to 1",
reading.name
);
}
Self {
id: id.into(),
readings,
}
}
}
impl RenderOnce for HardwareMonitor {
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
let spark = cx.theme().spark_size();
div()
.flex()
.flex_col()
.gap_3()
.children(self.readings.into_iter().enumerate().map(|(ix, reading)| {
div()
.flex()
.items_end()
.gap_3()
.child(
div().flex_1().min_w_0().child(
Meter::new(
(self.id.clone(), format!("meter-{ix}")),
reading.name,
reading.share,
)
.detail(reading.detail)
.thresholds(0.75, 0.9),
),
)
.when(reading.history.len() > 1, |row| {
row.child(
div()
.flex_none()
.w(spark.width)
.h(spark.height)
.child(Sparkline::new(reading.history).area()),
)
})
}))
}
}