use crate::core::buffer::Buffer;
use crate::core::color::Color;
use crate::core::rect::Rect;
use crate::widgets::Widget;
#[derive(Debug, Clone)]
pub struct Sparkline {
pub data: Vec<u64>,
pub max: Option<u64>,
pub color: Color,
pub bar_set: &'static str,
}
impl Sparkline {
pub fn new() -> Self {
Self {
data: Vec::new(),
max: None,
color: Color::rgb(88, 166, 255),
bar_set: " ▁▂▃▄▅▆▇█",
}
}
pub fn with_data(mut self, data: Vec<u64>) -> Self {
self.data = data;
self
}
pub fn with_max(mut self, max: u64) -> Self {
self.max = Some(max);
self
}
pub fn with_color(mut self, color: Color) -> Self {
self.color = color;
self
}
fn get_bar(&self, value: u64, max: u64) -> char {
if max == 0 {
return ' ';
}
let ratio = value as f32 / max as f32;
let idx = (ratio * (self.bar_set.len() - 1) as f32) as usize;
self.bar_set.chars().nth(idx).unwrap_or(' ')
}
}
impl Widget for Sparkline {
fn render(&self, buffer: &mut Buffer, area: Rect) {
if self.data.is_empty() || area.width == 0 {
return;
}
let max = self
.max
.unwrap_or_else(|| self.data.iter().copied().max().unwrap_or(1));
let w = area.width as usize;
for i in 0..w {
let data_idx = (i * self.data.len()) / w;
let value = self.data.get(data_idx).copied().unwrap_or(0);
let ch = self.get_bar(value, max);
buffer.set(
area.x as usize + i,
area.y as usize,
crate::core::buffer::Cell {
ch,
fg: self.color,
bg: None,
bold: false,
italic: false,
underlined: false,
},
);
}
}
}
impl Default for Sparkline {
fn default() -> Self {
Self::new()
}
}