use ratatui::layout::Rect;
use ratatui::style::Style;
use crate::geometry::Size;
use crate::surface::Surface;
use crate::view::{RenderCtx, View};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum SpinnerStyle {
#[default]
Braille,
Line,
Dots,
}
impl SpinnerStyle {
pub fn frames(self) -> &'static [&'static str] {
match self {
SpinnerStyle::Braille => &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
SpinnerStyle::Line => &["|", "/", "-", "\\"],
SpinnerStyle::Dots => &["⠂", "⠒", "⠐", "⠰", "⠠", "⠤", "⠄", "⠆"],
}
}
}
pub struct Spinner {
style: SpinnerStyle,
frame: u64,
color: Option<ratatui::style::Color>,
}
impl Spinner {
pub fn new(frame: u64) -> Self {
Self {
style: SpinnerStyle::default(),
frame,
color: None,
}
}
pub fn style(mut self, style: SpinnerStyle) -> Self {
self.style = style;
self
}
pub fn color(mut self, color: ratatui::style::Color) -> Self {
self.color = Some(color);
self
}
pub fn glyph(&self) -> &'static str {
let frames = self.style.frames();
frames[(self.frame as usize) % frames.len()]
}
}
impl View for Spinner {
fn measure(&self, _available: Size) -> Size {
Size::new(1, 1)
}
fn render(&self, area: Rect, surface: &mut Surface, ctx: &RenderCtx) {
if area.width == 0 || area.height == 0 {
return;
}
let color = self.color.unwrap_or(ctx.theme.accent);
surface.set_string(area.x, area.y, self.glyph(), Style::default().fg(color));
}
}