1use gpui::{relative, AnyElement, FontWeight, StyleRefinement, 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 pub(super) base: Div,
47 size: LabelSize,
48 weight: FontWeight,
49 line_height_style: LineHeightStyle,
50 pub(crate) color: Color,
51 strikethrough: bool,
52 italic: bool,
53 children: SmallVec<[AnyElement; 2]>,
54}
55
56impl LabelLike {
57 pub fn new() -> Self {
58 Self {
59 base: div(),
60 size: LabelSize::Default,
61 weight: FontWeight::default(),
62 line_height_style: LineHeightStyle::default(),
63 color: Color::Default,
64 strikethrough: false,
65 italic: false,
66 children: SmallVec::new(),
67 }
68 }
69}
70
71// Style methods.
72impl LabelLike {
73 fn style(&mut self) -> &mut StyleRefinement {
74 self.base.style()
75 }
76
77 gpui::margin_style_methods!({
78 visibility: pub
79 });
80}
81
82impl LabelCommon for LabelLike {
83 fn size(mut self, size: LabelSize) -> Self {
84 self.size = size;
85 self
86 }
87
88 fn weight(mut self, weight: FontWeight) -> Self {
89 self.weight = weight;
90 self
91 }
92
93 fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
94 self.line_height_style = line_height_style;
95 self
96 }
97
98 fn color(mut self, color: Color) -> Self {
99 self.color = color;
100 self
101 }
102
103 fn strikethrough(mut self, strikethrough: bool) -> Self {
104 self.strikethrough = strikethrough;
105 self
106 }
107
108 fn italic(mut self, italic: bool) -> Self {
109 self.italic = italic;
110 self
111 }
112}
113
114impl ParentElement for LabelLike {
115 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
116 self.children.extend(elements)
117 }
118}
119
120impl RenderOnce for LabelLike {
121 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
122 self.base
123 .when(self.strikethrough, |this| {
124 this.relative().child(
125 div()
126 .absolute()
127 .top_1_2()
128 .w_full()
129 .h_px()
130 .bg(Color::Hidden.color(cx)),
131 )
132 })
133 .map(|this| match self.size {
134 LabelSize::Large => this.text_ui_lg(cx),
135 LabelSize::Default => this.text_ui(cx),
136 LabelSize::Small => this.text_ui_sm(cx),
137 LabelSize::XSmall => this.text_ui_xs(cx),
138 })
139 .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
140 this.line_height(relative(1.))
141 })
142 .when(self.italic, |this| this.italic())
143 .text_color(self.color.color(cx))
144 .font_weight(self.weight)
145 .children(self.children)
146 }
147}