Skip to main content

cranpose_ui/text/
layout_options.rs

1/// How overflowing text should be handled.
2#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
3pub enum TextOverflow {
4    #[default]
5    Clip,
6    Ellipsis,
7    Visible,
8    StartEllipsis,
9    MiddleEllipsis,
10}
11
12/// Text layout behavior options matching Compose `BasicText` controls.
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub struct TextLayoutOptions {
15    pub overflow: TextOverflow,
16    pub soft_wrap: bool,
17    pub max_lines: usize,
18    pub min_lines: usize,
19}
20
21impl Default for TextLayoutOptions {
22    fn default() -> Self {
23        Self {
24            overflow: TextOverflow::Clip,
25            soft_wrap: true,
26            max_lines: usize::MAX,
27            min_lines: 1,
28        }
29    }
30}
31
32impl TextLayoutOptions {
33    pub fn normalized(self) -> Self {
34        let min_lines = self.min_lines.max(1);
35        let max_lines = self.max_lines.max(min_lines);
36        Self {
37            overflow: self.overflow,
38            soft_wrap: self.soft_wrap,
39            max_lines,
40            min_lines,
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn normalized_enforces_minimum_one_line() {
51        let options = TextLayoutOptions {
52            min_lines: 0,
53            max_lines: 0,
54            ..Default::default()
55        }
56        .normalized();
57
58        assert_eq!(options.min_lines, 1);
59        assert_eq!(options.max_lines, 1);
60    }
61
62    #[test]
63    fn normalized_ensures_max_not_smaller_than_min() {
64        let options = TextLayoutOptions {
65            min_lines: 3,
66            max_lines: 1,
67            ..Default::default()
68        }
69        .normalized();
70
71        assert_eq!(options.min_lines, 3);
72        assert_eq!(options.max_lines, 3);
73    }
74}