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
 46#[derive(IntoElement)]
 47pub struct LabelLike {
 48    pub(super) base: Div,
 49    size: LabelSize,
 50    weight: Option<FontWeight>,
 51    line_height_style: LineHeightStyle,
 52    pub(crate) color: Color,
 53    strikethrough: bool,
 54    italic: bool,
 55    children: SmallVec<[AnyElement; 2]>,
 56}
 57
 58impl LabelLike {
 59    pub fn new() -> Self {
 60        Self {
 61            base: div(),
 62            size: LabelSize::Default,
 63            weight: None,
 64            line_height_style: LineHeightStyle::default(),
 65            color: Color::Default,
 66            strikethrough: false,
 67            italic: false,
 68            children: SmallVec::new(),
 69        }
 70    }
 71}
 72
 73// Style methods.
 74impl LabelLike {
 75    fn style(&mut self) -> &mut StyleRefinement {
 76        self.base.style()
 77    }
 78
 79    gpui::margin_style_methods!({
 80        visibility: pub
 81    });
 82}
 83
 84impl LabelCommon for LabelLike {
 85    fn size(mut self, size: LabelSize) -> Self {
 86        self.size = size;
 87        self
 88    }
 89
 90    fn weight(mut self, weight: FontWeight) -> Self {
 91        self.weight = Some(weight);
 92        self
 93    }
 94
 95    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
 96        self.line_height_style = line_height_style;
 97        self
 98    }
 99
100    fn color(mut self, color: Color) -> Self {
101        self.color = color;
102        self
103    }
104
105    fn strikethrough(mut self, strikethrough: bool) -> Self {
106        self.strikethrough = strikethrough;
107        self
108    }
109
110    fn italic(mut self, italic: bool) -> Self {
111        self.italic = italic;
112        self
113    }
114}
115
116impl ParentElement for LabelLike {
117    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
118        self.children.extend(elements)
119    }
120}
121
122impl RenderOnce for LabelLike {
123    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
124        let settings = ThemeSettings::get_global(cx);
125
126        self.base
127            .when(self.strikethrough, |this| {
128                this.relative().child(
129                    div()
130                        .absolute()
131                        .top_1_2()
132                        .w_full()
133                        .h_px()
134                        .bg(Color::Hidden.color(cx)),
135                )
136            })
137            .map(|this| match self.size {
138                LabelSize::Large => this.text_ui_lg(cx),
139                LabelSize::Default => this.text_ui(cx),
140                LabelSize::Small => this.text_ui_sm(cx),
141                LabelSize::XSmall => this.text_ui_xs(cx),
142            })
143            .when(self.line_height_style == LineHeightStyle::UiLabel, |this| {
144                this.line_height(relative(1.))
145            })
146            .when(self.italic, |this| this.italic())
147            .text_color(self.color.color(cx))
148            .font_weight(self.weight.unwrap_or(settings.ui_font.weight))
149            .children(self.children)
150    }
151}