sparkline.rs (2270B)
1 use egui::{Color32, Pos2, Response, Sense, Stroke, Ui, Vec2}; 2 3 #[derive(Clone, Copy)] 4 pub struct SparkStyle { 5 pub stroke: Stroke, 6 //pub fill_alpha: u8, 7 //pub rounding: f32, 8 } 9 10 impl Default for SparkStyle { 11 fn default() -> Self { 12 Self { 13 stroke: Stroke::new(1.5, Color32::WHITE), 14 //fill_alpha: 40, 15 //rounding: 3.0, 16 } 17 } 18 } 19 20 /// values are samples over time (left=oldest, right=newest) 21 pub fn sparkline( 22 ui: &mut Ui, 23 size: Vec2, 24 values: &[f32], 25 color: Color32, 26 style: SparkStyle, 27 ) -> Response { 28 let (rect, resp) = ui.allocate_exact_size(size, Sense::hover()); 29 let painter = ui.painter_at(rect); 30 31 // background 32 //painter.rect_filled(rect, style.rounding, ui.visuals().widgets.inactive.bg_fill); 33 34 if values.len() < 2 { 35 return resp; 36 } 37 38 let mut min_v = f32::INFINITY; 39 let mut max_v = f32::NEG_INFINITY; 40 for &v in values { 41 let v = v.max(0.0); 42 min_v = min_v.min(v); 43 max_v = max_v.max(v); 44 } 45 // avoid div by zero, also allow flat lines 46 let span = (max_v - min_v).max(1.0); 47 48 let n = values.len(); 49 let dx = rect.width() / (n.saturating_sub(1) as f32).max(1.0); 50 51 let mut pts: Vec<Pos2> = Vec::with_capacity(n); 52 for (i, &v) in values.iter().enumerate() { 53 let t = (v.max(0.0) - min_v) / span; // 0..1 54 let x = rect.left() + (i as f32) * dx; 55 let y = rect.bottom() - t * rect.height(); 56 pts.push(Pos2::new(x, y)); 57 } 58 59 // fill under curve 60 /* 61 let mut fill_pts = Vec::with_capacity(pts.len() + 2); 62 fill_pts.extend_from_slice(&pts); 63 fill_pts.push(Pos2::new(rect.right(), rect.bottom())); 64 fill_pts.push(Pos2::new(rect.left(), rect.bottom())); 65 66 let mut fill_color = color; 67 fill_color = Color32::from_rgba_premultiplied( 68 fill_color.r(), 69 fill_color.g(), 70 fill_color.b(), 71 style.fill_alpha, 72 ); 73 74 painter.add(egui::Shape::Path(egui::epaint::PathShape { 75 points: fill_pts, 76 closed: true, 77 fill: fill_color, 78 stroke: Stroke::NONE.into(), 79 })); 80 */ 81 82 // line 83 painter.add(egui::Shape::line( 84 pts, 85 Stroke::new(style.stroke.width, color), 86 )); 87 88 resp 89 }