🔒 Repository is read-only – file editing is disabled.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
//! `Avatar` — okrągły awatar z inicjałami (zastępstwo obrazka).
//!
//! Widget immediate: [`Avatar::paint`] rysuje wypełniony okrąg z inicjałami. Rozmiar z tokenów
//! ([`AvatarMetrics`](libluna_core::AvatarMetrics)).
use libluna_core::style::weight;
use libluna_core::{Rect, Theme};
use crate::ctx::PaintCtx;
/// Awatar z inicjałami.
#[derive(Debug, Clone, Default)]
pub struct Avatar {
initials: String,
}
impl Avatar {
pub fn new(initials: impl Into<String>) -> Self {
Self {
initials: initials.into(),
}
}
pub fn initials(&self) -> &str {
&self.initials
}
/// Domyślna średnica awatara (z metryk).
pub fn size(&self, theme: &Theme) -> f64 {
theme.metrics.avatar.size
}
/// Rysuje awatar w (kwadratowym) prostokącie `rect`.
pub fn paint(&self, ctx: &mut PaintCtx, rect: Rect) {
let theme = *ctx.theme;
let radius = rect.width().min(rect.height()) / 2.0;
ctx.scene
.fill_rounded_rect(rect, radius, theme.colors.accent);
// Maksymalnie dwa znaki inicjałów (np. „Ada Lovelace” → „AL”).
let initials: String = self
.initials
.chars()
.take(2)
.collect::<String>()
.to_uppercase();
ctx.label_center(
rect.center().x,
rect.center().y,
&initials,
theme.typography.body.size,
weight::BOLD,
theme.colors.accent_fg,
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn size_from_metrics() {
let theme = Theme::light();
assert_eq!(Avatar::new("AL").size(&theme), theme.metrics.avatar.size);
assert_eq!(Avatar::new("AL").initials(), "AL");
}
}