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 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 line height style of the label using a [`LineHeightStyle`].
29 fn line_height_style(self, line_height_style: LineHeightStyle) -> Self;
30
31 /// Sets the color of the label using a [`Color`].
32 fn color(self, color: Color) -> Self;
33
34 /// Sets the strikethrough property of the label.
35 fn strikethrough(self, strikethrough: bool) -> Self;
36
37 /// Sets the italic property of the label.
38 fn italic(self, italic: bool) -> Self;
39}
40
41#[derive(IntoElement)]
42pub struct LabelLike {
43 size: LabelSize,
44 line_height_style: LineHeightStyle,
45 pub(crate) color: Color,
46 strikethrough: bool,
47 italic: bool,
48 children: SmallVec<[AnyElement; 2]>,
49}
50
51impl LabelLike {
52 pub fn new() -> Self {
53 Self {
54 size: LabelSize::Default,
55 line_height_style: LineHeightStyle::default(),
56 color: Color::Default,
57 strikethrough: false,
58 italic: false,
59 children: SmallVec::new(),
60 }
61 }
62}
63
64impl LabelCommon for LabelLike {
65 fn size(mut self, size: LabelSize) -> Self {
66 self.size = size;
67 self
68 }
69
70 fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
71 self.line_height_style = line_height_style;
72 self
73 }
74
75 fn color(mut self, color: Color) -> Self {
76 self.color = color;
77 self
78 }
79
80 fn strikethrough(mut self, strikethrough: bool) -> Self {
81 self.strikethrough = strikethrough;
82 self
83 }
84
85 fn italic(mut self, italic: bool) -> Self {
86 self.italic = italic;
87 self
88 }
89}
90
91impl ParentElement for LabelLike {
92 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
93 self.children.extend(elements)
94 }
95}
96
97impl RenderOnce for LabelLike {
98 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
99 div()
100 .when(self.strikethrough, |this| {
101 this.relative().child(
102 div()
103 .absolute()
104 .top_1_2()
105 .w_full()
106 .h_px()
107 .bg(Color::Hidden.color(cx)),
108 )
109 })
110 .map(|this| match self.size {
111 LabelSize::Large => this.text_ui_lg(cx),
112 LabelSize::Default => this.text_ui(cx),
113 LabelSize::Small => this.text_ui_sm(cx),
114 LabelSize::XSmall => this.text_ui_xs(cx),
115 })
116 .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
117 this.line_height(relative(1.))
118 })
119 .when(self.italic, |this| this.italic())
120 .text_color(self.color.color(cx))
121 .children(self.children)
122 }
123}