use std::panic::Location;
use crate::shader::{ShaderBinding, StockShader, UniformValue};
use crate::tokens;
use crate::tree::*;
pub const DEFAULT_SIZE: f32 = 16.0;
#[track_caller]
pub fn spinner() -> El {
spinner_with_color(tokens::FOREGROUND)
}
#[track_caller]
pub fn spinner_with_color(arc: Color) -> El {
spinner_with_track(arc, arc.with_alpha(0))
}
#[track_caller]
pub fn spinner_with_track(arc: Color, track: Color) -> El {
let binding = ShaderBinding::stock(StockShader::Spinner)
.with("vec_a", UniformValue::Color(arc))
.with("vec_b", UniformValue::Color(track))
.with("vec_c", UniformValue::Vec4([0.0, 0.0, 0.0, 0.0]));
El::new(Kind::Custom("spinner"))
.at_loc(Location::caller())
.shader(binding)
.default_width(Size::Fixed(DEFAULT_SIZE))
.default_height(Size::Fixed(DEFAULT_SIZE))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::shader::{ShaderHandle, UniformValue};
#[test]
fn spinner_binds_stock_spinner_shader() {
let s = spinner();
let binding = s.shader_override.as_ref().expect("shader binding");
assert_eq!(
binding.handle,
ShaderHandle::Stock(StockShader::Spinner),
"spinner widget must paint through stock::spinner"
);
}
#[test]
fn spinner_packs_color_into_vec_a() {
let s = spinner_with_color(tokens::PRIMARY);
let binding = s.shader_override.as_ref().unwrap();
match binding.uniforms.get("vec_a") {
Some(UniformValue::Color(c)) => assert_eq!(*c, tokens::PRIMARY),
other => panic!("expected vec_a=PRIMARY color, got {other:?}"),
}
}
#[test]
fn spinner_default_size_matches_icon_sm() {
let s = spinner();
assert_eq!(s.width, Size::Fixed(DEFAULT_SIZE));
assert_eq!(s.height, Size::Fixed(DEFAULT_SIZE));
assert_eq!(
DEFAULT_SIZE,
tokens::ICON_SM,
"spinner default size should match icon-sm so it drops into icon slots"
);
}
#[test]
fn spinner_kind_is_custom_spinner() {
let s = spinner();
assert_eq!(s.kind, Kind::Custom("spinner"));
}
#[test]
fn spinner_default_track_is_fully_transparent() {
let s = spinner_with_color(tokens::PRIMARY);
let binding = s.shader_override.as_ref().unwrap();
match binding.uniforms.get("vec_b") {
Some(UniformValue::Color(c)) => {
assert_eq!(c.a, 0, "default track must be fully transparent");
}
other => panic!("expected vec_b track color, got {other:?}"),
}
}
#[test]
fn spinner_with_track_uses_explicit_track() {
let s = spinner_with_track(tokens::SUCCESS, tokens::MUTED);
let binding = s.shader_override.as_ref().unwrap();
assert_eq!(
binding.uniforms.get("vec_b"),
Some(&UniformValue::Color(tokens::MUTED))
);
}
}