1use gpui::{relative, AnyElement, Styled};
2use smallvec::SmallVec;
3
4use crate::prelude::*;
5
6#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
7pub enum LabelSize {
8 #[default]
9 Default,
10 Small,
11 XSmall,
12}
13
14#[derive(Default, PartialEq, Copy, Clone)]
15pub enum LineHeightStyle {
16 #[default]
17 TextLabel,
18 /// Sets the line height to 1.
19 UiLabel,
20}
21
22/// A common set of traits all labels must implement.
23pub trait LabelCommon {
24 /// Sets the size of the label using a [`LabelSize`].
25 fn size(self, size: LabelSize) -> Self;
26
27 /// Sets the line height style of the label using a [`LineHeightStyle`].
28 fn line_height_style(self, line_height_style: LineHeightStyle) -> Self;
29
30 /// Sets the color of the label using a [`Color`].
31 fn color(self, color: Color) -> Self;
32
33 /// Sets the strikethrough property of the label.
34 fn strikethrough(self, strikethrough: bool) -> Self;
35}
36
37#[derive(IntoElement)]
38pub struct LabelLike {
39 size: LabelSize,
40 line_height_style: LineHeightStyle,
41 pub(crate) color: Color,
42 strikethrough: bool,
43 children: SmallVec<[AnyElement; 2]>,
44}
45
46impl LabelLike {
47 pub fn new() -> Self {
48 Self {
49 size: LabelSize::Default,
50 line_height_style: LineHeightStyle::default(),
51 color: Color::Default,
52 strikethrough: false,
53 children: SmallVec::new(),
54 }
55 }
56}
57
58impl LabelCommon for LabelLike {
59 fn size(mut self, size: LabelSize) -> Self {
60 self.size = size;
61 self
62 }
63
64 fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
65 self.line_height_style = line_height_style;
66 self
67 }
68
69 fn color(mut self, color: Color) -> Self {
70 self.color = color;
71 self
72 }
73
74 fn strikethrough(mut self, strikethrough: bool) -> Self {
75 self.strikethrough = strikethrough;
76 self
77 }
78}
79
80impl ParentElement for LabelLike {
81 fn extend(&mut self, elements: impl Iterator<Item = AnyElement>) {
82 self.children.extend(elements)
83 }
84}
85
86impl RenderOnce for LabelLike {
87 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
88 div()
89 .when(self.strikethrough, |this| {
90 this.relative().child(
91 div()
92 .absolute()
93 .top_1_2()
94 .w_full()
95 .h_px()
96 .bg(Color::Hidden.color(cx)),
97 )
98 })
99 .map(|this| match self.size {
100 LabelSize::Default => this.text_ui(),
101 LabelSize::Small => this.text_ui_sm(),
102 LabelSize::XSmall => this.text_ui_xs(),
103 })
104 .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
105 this.line_height(relative(1.))
106 })
107 .text_color(self.color.color(cx))
108 .children(self.children)
109 }
110}