label_like.rs

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