use crate::ui::core::gauge::Gauge;
use crate::ui::core::widget::Widget;
use ratatui::{
layout::Rect,
style::{Color, Modifier, Style},
widgets::Gauge as RatatuiGauge,
Frame,
};
pub fn ratio_color(ratio: f64) -> Color {
if ratio > 0.6 {
Color::Green
} else if ratio > 0.3 {
Color::Yellow
} else {
Color::Red
}
}
pub struct GaugeWidget {
ratio: f64,
label: Option<String>,
style: Style,
auto_color: bool,
}
impl GaugeWidget {
pub fn new() -> Self {
Self {
ratio: 0.0,
label: None,
style: Style::default(),
auto_color: false,
}
}
pub fn with_ratio(mut self, ratio: f64) -> Self {
self.ratio = ratio.clamp(0.0, 1.0);
self
}
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn with_style(mut self, style: Style) -> Self {
self.style = style;
self.auto_color = false; self
}
pub fn with_auto_color(mut self, enabled: bool) -> Self {
self.auto_color = enabled;
self
}
pub fn render(&self, frame: &mut Frame, area: Rect) {
let style = if self.auto_color {
Style::default()
.fg(ratio_color(self.ratio))
.add_modifier(Modifier::BOLD)
} else {
self.style
};
let gauge = RatatuiGauge::default()
.ratio(self.ratio)
.gauge_style(style)
.label(self.label.as_deref().unwrap_or(""));
frame.render_widget(gauge, area);
}
}
impl Default for GaugeWidget {
fn default() -> Self {
Self::new()
}
}
impl Widget for GaugeWidget {
fn widget_type(&self) -> &'static str {
"GaugeWidget"
}
}
impl Gauge for GaugeWidget {
fn ratio(&self) -> f64 {
self.ratio
}
fn set_ratio(&mut self, ratio: f64) {
self.ratio = ratio.clamp(0.0, 1.0);
}
fn label(&self) -> Option<&str> {
self.label.as_deref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ratio_color() {
assert_eq!(ratio_color(1.0), Color::Green);
assert_eq!(ratio_color(0.7), Color::Green);
assert_eq!(ratio_color(0.5), Color::Yellow);
assert_eq!(ratio_color(0.4), Color::Yellow);
assert_eq!(ratio_color(0.2), Color::Red);
assert_eq!(ratio_color(0.0), Color::Red);
}
#[test]
fn test_gauge_creation() {
let gauge = GaugeWidget::new()
.with_ratio(0.75)
.with_label("HP: 75/100")
.with_auto_color(true);
assert_eq!(gauge.ratio(), 0.75);
assert_eq!(gauge.label(), Some("HP: 75/100"));
}
#[test]
fn test_ratio_clamping() {
let mut gauge = GaugeWidget::new().with_ratio(1.5);
assert_eq!(gauge.ratio(), 1.0);
gauge.set_ratio(-0.5);
assert_eq!(gauge.ratio(), 0.0);
}
}