1use gpui::{relative, AnyElement, FontWeight, 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 Large,
11 Small,
12 XSmall,
13}
14
15#[derive(Default, PartialEq, Copy, Clone)]
16pub enum LineHeightStyle {
17 #[default]
18 TextLabel,
19 /// Sets the line height to 1.
20 UiLabel,
21}
22
23/// A common set of traits all labels must implement.
24pub trait LabelCommon {
25 /// Sets the size of the label using a [`LabelSize`].
26 fn size(self, size: LabelSize) -> Self;
27
28 /// Sets the font weight of the label.
29 fn weight(self, weight: FontWeight) -> Self;
30
31 /// Sets the line height style of the label using a [`LineHeightStyle`].
32 fn line_height_style(self, line_height_style: LineHeightStyle) -> Self;
33
34 /// Sets the color of the label using a [`Color`].
35 fn color(self, color: Color) -> Self;
36
37 /// Sets the strikethrough property of the label.
38 fn strikethrough(self, strikethrough: bool) -> Self;
39
40 /// Sets the italic property of the label.
41 fn italic(self, italic: bool) -> Self;
42}
43
44#[derive(IntoElement)]
45pub struct LabelLike {
46 size: LabelSize,
47 weight: FontWeight,
48 line_height_style: LineHeightStyle,
49 pub(crate) color: Color,
50 strikethrough: bool,
51 italic: bool,
52 children: SmallVec<[AnyElement; 2]>,
53}
54
55impl LabelLike {
56 pub fn new() -> Self {
57 Self {
58 size: LabelSize::Default,
59 weight: FontWeight::default(),
60 line_height_style: LineHeightStyle::default(),
61 color: Color::Default,
62 strikethrough: false,
63 italic: false,
64 children: SmallVec::new(),
65 }
66 }
67}
68
69impl LabelCommon for LabelLike {
70 fn size(mut self, size: LabelSize) -> Self {
71 self.size = size;
72 self
73 }
74
75 fn weight(mut self, weight: FontWeight) -> Self {
76 self.weight = weight;
77 self
78 }
79
80 fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
81 self.line_height_style = line_height_style;
82 self
83 }
84
85 fn color(mut self, color: Color) -> Self {
86 self.color = color;
87 self
88 }
89
90 fn strikethrough(mut self, strikethrough: bool) -> Self {
91 self.strikethrough = strikethrough;
92 self
93 }
94
95 fn italic(mut self, italic: bool) -> Self {
96 self.italic = italic;
97 self
98 }
99}
100
101impl ParentElement for LabelLike {
102 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
103 self.children.extend(elements)
104 }
105}
106
107impl RenderOnce for LabelLike {
108 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
109 div()
110 .when(self.strikethrough, |this| {
111 this.relative().child(
112 div()
113 .absolute()
114 .top_1_2()
115 .w_full()
116 .h_px()
117 .bg(Color::Hidden.color(cx)),
118 )
119 })
120 .map(|this| match self.size {
121 LabelSize::Large => this.text_ui_lg(cx),
122 LabelSize::Default => this.text_ui(cx),
123 LabelSize::Small => this.text_ui_sm(cx),
124 LabelSize::XSmall => this.text_ui_xs(cx),
125 })
126 .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
127 this.line_height(relative(1.))
128 })
129 .when(self.italic, |this| this.italic())
130 .text_color(self.color.color(cx))
131 .font_weight(self.weight)
132 .children(self.children)
133 }
134}