label_like.rs

  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}