use std::iter::zip;
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Rect},
style::Color,
widgets::Widget,
};
#[derive(Debug)]
pub struct Equalizer {
pub bands: Vec<Band>,
pub brightness: f64,
}
#[derive(Debug, Clone)]
pub struct Band {
pub value: f64,
}
impl From<f64> for Band {
fn from(value: f64) -> Self {
Self { value }
}
}
impl Widget for Equalizer {
fn render(self, area: Rect, buf: &mut Buffer) {
let areas = Layout::horizontal(vec![Constraint::Length(2); self.bands.len()]).split(area);
for (band, area) in zip(self.bands, areas.iter()) {
band.render(*area, buf, self.brightness);
}
}
}
impl Band {
fn render(self, area: Rect, buf: &mut Buffer, brightness: f64) {
let value = self.value.clamp(0.0, 1.0);
let height = (value * area.height as f64) as u16;
let color_step = 1.0 / area.height as f64;
for i in 0..height {
let v = i as f64 * color_step;
let vv = 1.0 - v;
let br = brightness.clamp(0.0, 1.0) * 255.0;
let r = if v < 0.5 { v * 2.0 * br } else { br } as u8;
let g = if v < 0.5 { br } else { vv * 2.0 * br } as u8;
let b = 0;
let color = Color::Rgb(r, g, b);
buf[(area.left(), area.bottom().saturating_sub(i + 1))]
.set_fg(color)
.set_symbol(ratatui::symbols::bar::HALF);
}
}
}