1use crate::common::Variant;
4use egui::{vec2, Color32, FontId, Response, Sense, Stroke, Ui, Widget, WidgetText};
5use egui_components_theme::{Theme, ThemeColor};
6
7pub struct Badge {
8 label: WidgetText,
9 variant: Variant,
10 outlined: bool,
11}
12
13impl Badge {
14 pub fn new(label: impl Into<WidgetText>) -> Self {
15 Self {
16 label: label.into(),
17 variant: Variant::Primary,
18 outlined: false,
19 }
20 }
21 pub fn variant(mut self, v: Variant) -> Self {
22 self.variant = v;
23 self
24 }
25 pub fn outlined(mut self) -> Self {
26 self.outlined = true;
27 self
28 }
29}
30
31impl Widget for Badge {
32 fn ui(self, ui: &mut Ui) -> Response {
33 let theme = Theme::get(ui.ctx());
34 let m = theme.metrics;
35 let pad_x = 8.0;
36 let pad_y = 2.0;
37 let font = FontId::proportional(m.font_size_xs);
38 let galley = self.label.into_galley(
39 ui,
40 Some(egui::TextWrapMode::Extend),
41 f32::INFINITY,
42 font,
43 );
44 let desired = vec2(galley.size().x + pad_x * 2.0, galley.size().y + pad_y * 2.0);
45 let (rect, response) = ui.allocate_exact_size(desired, Sense::hover());
46
47 if ui.is_rect_visible(rect) {
48 let (bg, fg) = variant_colors(&theme.colors, self.variant);
49 let radius = egui::CornerRadius::same((desired.y * 0.5) as u8);
50 let painter = ui.painter();
51
52 if self.outlined {
53 painter.rect(
54 rect,
55 radius,
56 Color32::TRANSPARENT,
57 Stroke::new(1.0, bg),
58 egui::StrokeKind::Inside,
59 );
60 painter.galley_with_override_text_color(
61 rect.center() - galley.size() * 0.5,
62 galley,
63 bg,
64 );
65 } else {
66 painter.rect_filled(rect, radius, bg);
67 painter.galley_with_override_text_color(
68 rect.center() - galley.size() * 0.5,
69 galley,
70 fg,
71 );
72 }
73 }
74
75 response
76 }
77}
78
79fn variant_colors(c: &ThemeColor, v: Variant) -> (Color32, Color32) {
80 match v {
81 Variant::Primary => (c.primary_background, c.primary_foreground),
82 Variant::Secondary => (c.secondary_background, c.secondary_foreground),
83 Variant::Ghost => (c.muted_background, c.muted_foreground),
84 Variant::Outline => (c.foreground, c.background),
85 Variant::Link => (c.link_foreground, c.background),
86 Variant::Danger => (c.danger_background, c.danger_foreground),
87 Variant::Success => (c.success_background, c.success_foreground),
88 Variant::Warning => (c.warning_background, c.warning_foreground),
89 Variant::Info => (c.info_background, c.info_foreground),
90 }
91}