use egui::{FontId, Response, Sense, Stroke, TextStyle, Ui, Widget, vec2};
use super::corner;
use crate::{Icon, RADIUS, SPACING, palette_of};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Trend {
Up,
Down,
Flat,
}
pub struct Stat<'a> {
label: &'a str,
value: &'a str,
delta: Option<(&'a str, Trend)>,
}
impl<'a> Stat<'a> {
pub fn new(label: &'a str) -> Self {
Self {
label,
value: "",
delta: None,
}
}
pub fn value(mut self, value: &'a str) -> Self {
self.value = value;
self
}
pub fn delta(mut self, text: &'a str, trend: Trend) -> Self {
self.delta = Some((text, trend));
self
}
}
impl<'a> Widget for Stat<'a> {
fn ui(self, ui: &mut Ui) -> Response {
let palette = palette_of(ui.ctx());
let frame = egui::Frame::default()
.fill(palette.bg_surface)
.stroke(Stroke::new(1.0, palette.border_subtle))
.corner_radius(corner(RADIUS.md))
.inner_margin(egui::Margin::same(SPACING.s4 as i8));
frame
.show(ui, |ui| {
ui.set_min_width(140.0);
ui.label(
egui::RichText::new(self.label)
.text_style(TextStyle::Small)
.color(palette.text_secondary),
);
ui.add_space(SPACING.s1);
ui.label(
egui::RichText::new(self.value)
.font(FontId::new(28.0, egui::FontFamily::Proportional))
.color(palette.text_primary),
);
if let Some((text, trend)) = self.delta {
ui.add_space(SPACING.s1);
ui.horizontal(|ui| {
let (icon, color) = match trend {
Trend::Up => (Icon::ChevronUp, palette.success),
Trend::Down => (Icon::ChevronDown, palette.error),
Trend::Flat => (Icon::ChevronRight, palette.text_secondary),
};
let (rect, _) = ui.allocate_exact_size(vec2(14.0, 14.0), Sense::hover());
icon.paint(ui.painter(), rect, color);
ui.label(
egui::RichText::new(text)
.font(FontId::new(12.0, egui::FontFamily::Proportional))
.color(color),
);
});
}
})
.response
}
}