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 LabelLike {
 63    pub fn new() -> Self {
 64        Self {
 65            base: div(),
 66            size: LabelSize::Default,
 67            weight: None,
 68            line_height_style: LineHeightStyle::default(),
 69            color: Color::Default,
 70            strikethrough: false,
 71            italic: false,
 72            children: SmallVec::new(),
 73            alpha: None,
 74        }
 75    }
 76}
 77
 78// Style methods.
 79impl LabelLike {
 80    fn style(&mut self) -> &mut StyleRefinement {
 81        self.base.style()
 82    }
 83
 84    gpui::margin_style_methods!({
 85        visibility: pub
 86    });
 87}
 88
 89impl LabelCommon for LabelLike {
 90    fn size(mut self, size: LabelSize) -> Self {
 91        self.size = size;
 92        self
 93    }
 94
 95    fn weight(mut self, weight: FontWeight) -> Self {
 96        self.weight = Some(weight);
 97        self
 98    }
 99
100    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
101        self.line_height_style = line_height_style;
102        self
103    }
104
105    fn color(mut self, color: Color) -> Self {
106        self.color = color;
107        self
108    }
109
110    fn strikethrough(mut self, strikethrough: bool) -> Self {
111        self.strikethrough = strikethrough;
112        self
113    }
114
115    fn italic(mut self, italic: bool) -> Self {
116        self.italic = italic;
117        self
118    }
119
120    fn alpha(mut self, alpha: f32) -> Self {
121        self.alpha = Some(alpha);
122        self
123    }
124}
125
126impl ParentElement for LabelLike {
127    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
128        self.children.extend(elements)
129    }
130}
131
132impl RenderOnce for LabelLike {
133    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
134        let settings = ThemeSettings::get_global(cx);
135
136        let mut color = self.color.color(cx);
137        if let Some(alpha) = self.alpha {
138            color.fade_out(1.0 - alpha);
139        }
140
141        self.base
142            .when(self.strikethrough, |this| {
143                this.relative().child(
144                    div()
145                        .absolute()
146                        .top_1_2()
147                        .w_full()
148                        .h_px()
149                        .bg(Color::Hidden.color(cx)),
150                )
151            })
152            .map(|this| match self.size {
153                LabelSize::Large => this.text_ui_lg(cx),
154                LabelSize::Default => this.text_ui(cx),
155                LabelSize::Small => this.text_ui_sm(cx),
156                LabelSize::XSmall => this.text_ui_xs(cx),
157            })
158            .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
159                this.line_height(relative(1.))
160            })
161            .when(self.italic, |this| this.italic())
162            .text_color(color)
163            .font_weight(self.weight.unwrap_or(settings.ui_font.weight))
164            .children(self.children)
165    }
166}