1use gpui::{relative, AnyElement, FontWeight, StyleRefinement, Styled};
2use settings::Settings;
3use smallvec::SmallVec;
4use theme::ThemeSettings;
5
6use crate::prelude::*;
7
8#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
9pub enum LabelSize {
10 #[default]
11 Default,
12 Large,
13 Small,
14 XSmall,
15}
16
17#[derive(Default, PartialEq, Copy, Clone)]
18pub enum LineHeightStyle {
19 #[default]
20 TextLabel,
21 /// Sets the line height to 1.
22 UiLabel,
23}
24
25/// A common set of traits all labels must implement.
26pub trait LabelCommon {
27 /// Sets the size of the label using a [`LabelSize`].
28 fn size(self, size: LabelSize) -> Self;
29
30 /// Sets the font weight of the label.
31 fn weight(self, weight: FontWeight) -> Self;
32
33 /// Sets the line height style of the label using a [`LineHeightStyle`].
34 fn line_height_style(self, line_height_style: LineHeightStyle) -> Self;
35
36 /// Sets the color of the label using a [`Color`].
37 fn color(self, color: Color) -> Self;
38
39 /// Sets the strikethrough property of the label.
40 fn strikethrough(self, strikethrough: bool) -> Self;
41
42 /// Sets the italic property of the label.
43 fn italic(self, italic: bool) -> Self;
44
45 /// Sets the alpha property of the label, overwriting the alpha value of the color.
46 fn alpha(self, alpha: f32) -> Self;
47}
48
49#[derive(IntoElement)]
50pub struct LabelLike {
51 pub(super) base: Div,
52 size: LabelSize,
53 weight: Option<FontWeight>,
54 line_height_style: LineHeightStyle,
55 pub(crate) color: Color,
56 strikethrough: bool,
57 italic: bool,
58 children: SmallVec<[AnyElement; 2]>,
59 alpha: Option<f32>,
60}
61
62impl Default for LabelLike {
63 fn default() -> Self {
64 Self::new()
65 }
66}
67
68impl LabelLike {
69 pub fn new() -> Self {
70 Self {
71 base: div(),
72 size: LabelSize::Default,
73 weight: None,
74 line_height_style: LineHeightStyle::default(),
75 color: Color::Default,
76 strikethrough: false,
77 italic: false,
78 children: SmallVec::new(),
79 alpha: None,
80 }
81 }
82}
83
84// Style methods.
85impl LabelLike {
86 fn style(&mut self) -> &mut StyleRefinement {
87 self.base.style()
88 }
89
90 gpui::margin_style_methods!({
91 visibility: pub
92 });
93}
94
95impl LabelCommon for LabelLike {
96 fn size(mut self, size: LabelSize) -> Self {
97 self.size = size;
98 self
99 }
100
101 fn weight(mut self, weight: FontWeight) -> Self {
102 self.weight = Some(weight);
103 self
104 }
105
106 fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
107 self.line_height_style = line_height_style;
108 self
109 }
110
111 fn color(mut self, color: Color) -> Self {
112 self.color = color;
113 self
114 }
115
116 fn strikethrough(mut self, strikethrough: bool) -> Self {
117 self.strikethrough = strikethrough;
118 self
119 }
120
121 fn italic(mut self, italic: bool) -> Self {
122 self.italic = italic;
123 self
124 }
125
126 fn alpha(mut self, alpha: f32) -> Self {
127 self.alpha = Some(alpha);
128 self
129 }
130}
131
132impl ParentElement for LabelLike {
133 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
134 self.children.extend(elements)
135 }
136}
137
138impl RenderOnce for LabelLike {
139 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
140 let settings = ThemeSettings::get_global(cx);
141
142 let mut color = self.color.color(cx);
143 if let Some(alpha) = self.alpha {
144 color.fade_out(1.0 - alpha);
145 }
146
147 self.base
148 .when(self.strikethrough, |this| {
149 this.relative().child(
150 div()
151 .absolute()
152 .top_1_2()
153 .w_full()
154 .h_px()
155 .bg(Color::Hidden.color(cx)),
156 )
157 })
158 .map(|this| match self.size {
159 LabelSize::Large => this.text_ui_lg(cx),
160 LabelSize::Default => this.text_ui(cx),
161 LabelSize::Small => this.text_ui_sm(cx),
162 LabelSize::XSmall => this.text_ui_xs(cx),
163 })
164 .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
165 this.line_height(relative(1.))
166 })
167 .when(self.italic, |this| this.italic())
168 .text_color(color)
169 .font_weight(self.weight.unwrap_or(settings.ui_font.weight))
170 .children(self.children)
171 }
172}