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