use crate::core::buffer::Buffer;
use crate::core::color::Color;
use crate::core::rect::Rect;
use aisling::color::{Color as AislingColor, Gradient as AislingGradient, GradientDirection};
use aisling::loaders::{Loader, LoaderConfig, LoaderKind, LoaderProgress};
pub struct LoaderPlayer {
kind: LoaderKind,
config: LoaderConfig,
accent: Color,
}
impl LoaderPlayer {
pub fn new(kind: LoaderKind) -> Self {
Self {
kind,
config: LoaderConfig::default(),
accent: Color::rgb(88, 166, 255),
}
}
pub fn with_config(kind: LoaderKind, config: LoaderConfig) -> Self {
Self {
kind,
config,
accent: Color::rgb(88, 166, 255),
}
}
pub fn with_accent(mut self, accent: Color) -> Self {
self.accent = accent;
self
}
pub fn with_size(mut self, width: usize, height: usize) -> Self {
self.config = self.config.with_size(width, height);
self
}
pub fn with_label(mut self, label: String) -> Self {
self.config = self.config.with_label(label);
self
}
pub fn with_unit(mut self, unit: &str) -> Self {
self.config = self.config.with_unit(unit);
self
}
pub fn with_fraction(mut self, fraction: bool) -> Self {
self.config = self.config.with_fraction(fraction);
self
}
pub fn with_gradient_colors(mut self, colors: Vec<Color>, angle: f32) -> Self {
let a_colors: Vec<AislingColor> = colors
.into_iter()
.map(|c| AislingColor::rgb(c.r, c.g, c.b))
.collect();
let grad = AislingGradient::new(a_colors, 32);
let dir = match angle as u32 {
0 => GradientDirection::Horizontal,
90 => GradientDirection::Vertical,
_ => GradientDirection::Diagonal,
};
self.config = self.config.with_gradient(grad, dir);
self
}
pub fn render(&self, tick: usize, progress: LoaderProgress, buffer: &mut Buffer, area: Rect) {
let loader = Loader::with_config(self.kind, self.config.clone());
let frame = loader.frame(tick, progress);
let fw = frame.width();
let fh = frame.height();
for fy in 0..fh.min(area.height as usize) {
for fx in 0..fw.min(area.width as usize) {
if let Some(cell) = frame.cell(fx, fy) {
let x = area.x as usize + fx;
let y = area.y as usize + fy;
if x < buffer.width && y < buffer.height {
let fg = if let Some(c) = cell.colors.fg {
Color::rgb(c.r, c.g, c.b)
} else {
self.accent
};
let bg = cell.colors.bg.map(|c| Color::rgb(c.r, c.g, c.b));
buffer.set(
x,
y,
crate::core::buffer::Cell {
ch: cell.ch,
fg,
bg,
bold: cell.bold,
italic: false,
underlined: false,
},
);
}
}
}
}
}
pub fn get_ansi_string(&self, tick: usize, progress: LoaderProgress) -> String {
let loader = Loader::with_config(self.kind, self.config.clone());
loader.frame(tick, progress).to_ansi_string()
}
pub fn kind(&self) -> LoaderKind {
self.kind
}
pub fn name(&self) -> &'static str {
self.kind.name()
}
pub fn all_kinds() -> &'static [LoaderKind] {
LoaderKind::all()
}
pub fn progress_from_counts(current: u64, total: u64) -> LoaderProgress {
LoaderProgress::from_counts(current, total)
}
pub fn progress_from_fraction(fraction: f32) -> LoaderProgress {
LoaderProgress::new(fraction)
}
}