gemini_engine/ascii/
text.rs

1use crate::core::{CanDraw, ColChar, Modifier, Vec2D};
2
3use super::TextAlign;
4
5/// Displays text at the given position
6#[non_exhaustive]
7#[derive(Debug, Clone)]
8pub struct Text {
9    /// The position that the text is drawn from.
10    pub pos: Vec2D,
11    /// The actual text content of the element
12    pub content: String,
13    /// How the content should align to the `pos` property
14    pub align: TextAlign,
15    /// A raw [`Modifier`], determining the appearance of the `Text`
16    pub modifier: Modifier,
17}
18
19impl Text {
20    /// Create a new Text element with a position, content and modifier
21    ///
22    /// # Panics
23    /// This function will panic if the content contains a newline, as Text only works with single lines. For multi-line strings, see [Sprite](super::Sprite)
24    #[must_use]
25    pub fn new(pos: Vec2D, content: &str, modifier: Modifier) -> Self {
26        assert!(
27            !content.contains('\n'),
28            "Text was created with a content string containing a \n character"
29        );
30
31        Self {
32            pos,
33            content: String::from(content),
34            align: TextAlign::Begin,
35            modifier,
36        }
37    }
38
39    /// Return the `Text` with an updated `align` property. Consumes the original `Text`
40    #[must_use]
41    pub const fn with_align(mut self, align: TextAlign) -> Self {
42        self.align = align;
43        self
44    }
45}
46
47impl CanDraw for Text {
48    fn draw_to(&self, canvas: &mut impl crate::core::Canvas) {
49        let mut pos = self.pos;
50        pos.x = self.align.apply_to(pos.x, self.content.len() as i64);
51
52        for (x, text_char) in (0..).zip(self.content.chars()) {
53            if text_char != ' ' {
54                canvas.plot(
55                    pos + Vec2D::new(x, 0),
56                    ColChar::new(text_char, self.modifier),
57                );
58            }
59        }
60    }
61}