Skip to main content

photon_ui/components/
truncated_text.rs

1use crate::{
2    Component,
3    RenderError,
4    Rendered,
5    utils::truncate_to_width,
6};
7
8/// Static text that is truncated with an ellipsis if it exceeds the available
9/// width.
10///
11/// Each line is padded with `pad_x` spaces and truncated independently.
12/// `pad_y` empty lines are added before and after the content.
13pub struct TruncatedText {
14    text: String,
15    pad_x: u16,
16    pad_y: u16,
17}
18
19impl TruncatedText {
20    /// Create a new truncated text component.
21    pub fn new(text: impl Into<String>, pad_x: u16, pad_y: u16) -> Self {
22        Self {
23            text: text.into(),
24            pad_x,
25            pad_y,
26        }
27    }
28}
29
30impl Component for TruncatedText {
31    fn render(&self, width: u16) -> Result<Rendered, RenderError> {
32        let mut lines = Vec::new();
33        for _ in 0..self.pad_y {
34            lines.push("".to_string());
35        }
36        let pad = " ".repeat(self.pad_x as usize);
37        let avail = width.saturating_sub(self.pad_x * 2);
38        for line in self.text.lines() {
39            let truncated = truncate_to_width(line, avail, "…");
40            lines.push(format!("{}{}", pad, truncated));
41        }
42        for _ in 0..self.pad_y {
43            lines.push("".to_string());
44        }
45        Ok(Rendered {
46            lines,
47            cursor: None,
48            images: Vec::new(),
49        })
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn truncated_text_with_padding() {
59        let t = TruncatedText::new("hello", 2, 1);
60        let r = t.render(20).unwrap();
61        assert_eq!(r.lines.len(), 3); // pad_y top + content + pad_y bottom
62        assert!(r.lines[0].is_empty());
63        assert!(r.lines[1].starts_with("  hello"));
64        assert!(r.lines[2].is_empty());
65    }
66
67    #[test]
68    fn truncated_text_empty_with_padding() {
69        let t = TruncatedText::new("", 0, 2);
70        let r = t.render(10).unwrap();
71        assert_eq!(r.lines.len(), 4);
72    }
73}