use eframe::egui::{self, Color32, CornerRadius, Sense, Shape, Stroke, pos2, vec2};
use crate::theme::Palette;
const HEIGHT: f32 = 56.0;
pub fn show(
ui: &mut egui::Ui,
p: &Palette,
values: &[f64],
max: f64,
color: Color32,
scale: &str,
format: impl Fn(f64) -> String,
) {
let (rect, response) =
ui.allocate_exact_size(vec2(ui.available_width(), HEIGHT), Sense::hover());
let painter = ui.painter_at(rect);
painter.rect(
rect,
CornerRadius::same(6),
p.bg,
Stroke::new(1.0, p.border),
egui::StrokeKind::Inside,
);
painter.text(
rect.right_top() + vec2(-6.0, 4.0),
egui::Align2::RIGHT_TOP,
scale,
egui::FontId::proportional(10.5),
p.muted,
);
if values.len() < 2 || max <= 0.0 {
return;
}
let inner = rect.shrink(4.0);
let step = inner.width() / (values.len() - 1) as f32;
let points: Vec<egui::Pos2> = values
.iter()
.enumerate()
.map(|(i, v)| {
let t = (v / max).clamp(0.0, 1.0) as f32;
pos2(
inner.left() + i as f32 * step,
inner.bottom() - t * inner.height(),
)
})
.collect();
let fill = color.gamma_multiply(0.18);
for pair in points.windows(2) {
let (a, b) = (pair[0], pair[1]);
painter.add(Shape::convex_polygon(
vec![a, b, pos2(b.x, inner.bottom()), pos2(a.x, inner.bottom())],
fill,
Stroke::NONE,
));
}
let hovered = response
.hover_pos()
.map(|pos| (((pos.x - inner.left()) / step).round() as usize).min(values.len() - 1));
painter.add(Shape::line(points.clone(), Stroke::new(1.5, color)));
if let Some(i) = hovered {
let point = points[i];
painter.line_segment(
[pos2(point.x, inner.top()), pos2(point.x, inner.bottom())],
Stroke::new(1.0, p.muted.gamma_multiply(0.6)),
);
painter.circle(point, 3.5, p.bg, Stroke::new(1.5, color));
let ago = values.len() - 1 - i;
let when = if ago == 0 {
"now".to_owned()
} else {
format!("{ago}s ago")
};
response.on_hover_text_at_pointer(format!("{} ยท {when}", format(values[i])));
}
}
pub fn tiny(ui: &mut egui::Ui, values: &[f64], max: f64, color: Color32, size: egui::Vec2) {
let (rect, _) = ui.allocate_exact_size(size, Sense::hover());
if values.len() < 2 || max <= 0.0 {
return;
}
let step = rect.width() / (values.len() - 1) as f32;
let points: Vec<egui::Pos2> = values
.iter()
.enumerate()
.map(|(i, v)| {
let t = (v / max).clamp(0.0, 1.0) as f32;
pos2(
rect.left() + i as f32 * step,
rect.bottom() - t * rect.height(),
)
})
.collect();
ui.painter()
.add(Shape::line(points, Stroke::new(1.3, color)));
}