Skip to main content

ply_engine/
text.rs

1use crate::align::AlignX;
2use crate::color::Color;
3use crate::renderer::FontAsset;
4use crate::shaders::{ShaderAsset, ShaderBuilder, ShaderConfig};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7#[repr(u8)]
8pub enum WrapMode {
9    /// Wraps on whitespaces not breaking words
10    #[default]
11    Words,
12    /// Only wraps on new line characters
13    Newline,
14    /// Never wraps, can overflow of parent layout
15    None,
16}
17
18/// Configuration settings for rendering text elements.
19#[derive(Debug, Clone)]
20pub struct TextConfig {
21    /// Internal engine user data.
22    pub(crate) user_data: usize,
23    /// The color of the text.
24    pub color: Color,
25    /// The font asset to use. `None` means use the default font.
26    pub font_asset: Option<&'static FontAsset>,
27    /// The font size of the text.
28    pub font_size: u16,
29    /// The spacing between letters.
30    pub letter_spacing: u16,
31    /// The height of each line of text.
32    pub line_height: u16,
33    /// Defines the text wrapping behavior.
34    pub wrap_mode: WrapMode,
35    /// The alignment of the text.
36    pub alignment: AlignX,
37    /// Per-element shader effects applied to this text.
38    pub(crate) effects: Vec<ShaderConfig>,
39    /// When true, the text content is exposed to screen readers as static text.
40    pub(crate) accessible: bool,
41}
42
43impl TextConfig {
44    /// Creates a new `TextConfig` instance with default values.
45    pub(crate) fn new() -> Self {
46        Self::default()
47    }
48
49    /// Sets the text color.
50    #[inline]
51    pub fn color(&mut self, color: impl Into<Color>) -> &mut Self {
52        self.color = color.into();
53        self
54    }
55
56    /// Sets the font to use for this text element.
57    #[inline]
58    pub fn font(&mut self, asset: &'static FontAsset) -> &mut Self {
59        self.font_asset = Some(asset);
60        self
61    }
62
63    /// Sets the font size.
64    #[inline]
65    pub fn font_size(&mut self, size: u16) -> &mut Self {
66        self.font_size = size;
67        self
68    }
69
70    /// Sets the letter spacing.
71    #[inline]
72    pub fn letter_spacing(&mut self, spacing: u16) -> &mut Self {
73        self.letter_spacing = spacing;
74        self
75    }
76
77    /// Sets the line height.
78    #[inline]
79    pub fn line_height(&mut self, height: u16) -> &mut Self {
80        self.line_height = height;
81        self
82    }
83
84    /// Sets the text wrapping mode.
85    #[inline]
86    pub fn wrap_mode(&mut self, mode: WrapMode) -> &mut Self {
87        self.wrap_mode = mode;
88        self
89    }
90
91    /// Sets the text alignment.
92    #[inline]
93    pub fn alignment(&mut self, alignment: AlignX) -> &mut Self {
94        self.alignment = alignment;
95        self
96    }
97
98    /// Adds a per-element shader effect to this text.
99    #[inline]
100    pub fn effect(&mut self, asset: &ShaderAsset, f: impl FnOnce(&mut ShaderBuilder<'_>)) -> &mut Self {
101        let mut builder = ShaderBuilder::new(asset);
102        f(&mut builder);
103        self.effects.push(builder.into_config());
104        self
105    }
106
107    /// Makes this text element visible to screen readers.
108    ///
109    /// ```ignore
110    /// ui.text("Hello world", |t| t.font_size(16).accessible());
111    /// ```
112    #[inline]
113    pub fn accessible(&mut self) -> &mut Self {
114        self.accessible = true;
115        self
116    }
117}
118
119impl Default for TextConfig {
120    fn default() -> Self {
121        Self {
122            user_data: 0,
123            color: Color::rgba(0., 0., 0., 0.),
124            font_size: 0,
125            letter_spacing: 0,
126            line_height: 0,
127            wrap_mode: WrapMode::Words,
128            alignment: AlignX::Left,
129            effects: Vec::new(),
130            font_asset: None,
131            accessible: false,
132        }
133    }
134}