armas_basic/components/
avatar.rs1use crate::ext::ArmasContextExt;
6use egui::{vec2, Response, Sense, Ui};
7
8const DEFAULT_SIZE: f32 = 32.0; #[derive(Debug, Clone, Copy, PartialEq, Default)]
13pub enum AvatarSize {
14 XSmall,
16 #[default]
18 Small,
19 Medium,
21 Large,
23 XLarge,
25 Custom(f32),
27}
28
29impl AvatarSize {
30 const fn to_pixels(self) -> f32 {
31 match self {
32 Self::XSmall => 24.0,
33 Self::Small => 32.0,
34 Self::Medium => 40.0,
35 Self::Large => 48.0,
36 Self::XLarge => 64.0,
37 Self::Custom(size) => size,
38 }
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
44pub enum AvatarShape {
45 #[default]
47 Circle,
48 Rounded,
50}
51
52pub struct Avatar {
71 text: String,
72 size: f32,
73 shape: AvatarShape,
74}
75
76impl Avatar {
77 pub fn new(text: impl Into<String>) -> Self {
79 Self {
80 text: text.into(),
81 size: DEFAULT_SIZE,
82 shape: AvatarShape::Circle,
83 }
84 }
85
86 #[must_use]
88 pub const fn size(mut self, size: f32) -> Self {
89 self.size = size;
90 self
91 }
92
93 #[must_use]
95 pub const fn size_preset(mut self, size: AvatarSize) -> Self {
96 self.size = size.to_pixels();
97 self
98 }
99
100 #[must_use]
102 pub const fn shape(mut self, shape: AvatarShape) -> Self {
103 self.shape = shape;
104 self
105 }
106
107 pub fn show(self, ui: &mut Ui) -> Response {
109 let theme = ui.ctx().armas_theme();
110 let (rect, response) = ui.allocate_exact_size(vec2(self.size, self.size), Sense::hover());
111
112 if ui.is_rect_visible(rect) {
113 let rounding = match self.shape {
115 AvatarShape::Circle => self.size / 2.0,
116 AvatarShape::Rounded => 6.0, };
118
119 ui.painter().rect_filled(rect, rounding, theme.muted());
121
122 let font_size = self.size * 0.4;
124 let font_id = egui::FontId::proportional(font_size);
125
126 let initials: String = self
128 .text
129 .split_whitespace()
130 .filter_map(|word| word.chars().next())
131 .take(2)
132 .collect::<String>()
133 .to_uppercase();
134
135 let display_text = if initials.is_empty() {
136 self.text.chars().take(2).collect::<String>().to_uppercase()
137 } else {
138 initials
139 };
140
141 ui.painter().text(
142 rect.center(),
143 egui::Align2::CENTER_CENTER,
144 display_text,
145 font_id,
146 theme.muted_foreground(),
147 );
148 }
149
150 response
151 }
152}