embedded_text/plugin/
tail.rs1use az::SaturatingAs;
4use embedded_graphics::{
5 prelude::PixelColor,
6 text::renderer::{CharacterStyle, TextRenderer},
7};
8
9use crate::{
10 plugin::Plugin,
11 rendering::{cursor::Cursor, TextBoxProperties},
12};
13
14#[derive(Copy, Clone)]
19pub struct Tail;
20
21impl<'a, C: PixelColor> Plugin<'a, C> for Tail {
22 fn on_start_render<S: CharacterStyle + TextRenderer>(
23 &mut self,
24 cursor: &mut Cursor,
25 props: &TextBoxProperties<'_, S>,
26 ) {
27 let box_height = props.bounding_box.size.height.saturating_as();
28 if props.text_height > box_height {
29 let offset = box_height - props.text_height;
30
31 cursor.y += offset;
32 }
33 }
34}
35
36#[cfg(test)]
37mod test {
38 use embedded_graphics::{
39 mock_display::MockDisplay,
40 mono_font::{ascii::FONT_6X9, MonoTextStyleBuilder},
41 pixelcolor::BinaryColor,
42 prelude::{Point, Size},
43 primitives::Rectangle,
44 Drawable,
45 };
46
47 use crate::{plugin::tail::Tail, style::TextBoxStyle, utils::test::size_for, TextBox};
48
49 #[track_caller]
50 pub fn assert_rendered(text: &str, size: Size, pattern: &[&str]) {
51 let mut display = MockDisplay::new();
52
53 let character_style = MonoTextStyleBuilder::new()
54 .font(&FONT_6X9)
55 .text_color(BinaryColor::On)
56 .background_color(BinaryColor::Off)
57 .build();
58
59 let style = TextBoxStyle::default();
60
61 TextBox::with_textbox_style(
62 text,
63 Rectangle::new(Point::zero(), size),
64 character_style,
65 style,
66 )
67 .add_plugin(Tail)
68 .draw(&mut display)
69 .unwrap();
70
71 display.assert_pattern(pattern);
72 }
73
74 #[test]
75 fn scrolling_behaves_as_top_if_lines_dont_overflow() {
76 assert_rendered(
77 "word",
78 size_for(&FONT_6X9, 4, 2),
79 &[
80 "........................",
81 "......................#.",
82 "......................#.",
83 "#...#...##...#.#....###.",
84 "#.#.#..#..#..##.#..#..#.",
85 "#.#.#..#..#..#.....#..#.",
86 ".#.#....##...#......###.",
87 "........................",
88 "........................",
89 " ",
90 " ",
91 " ",
92 " ",
93 " ",
94 " ",
95 " ",
96 " ",
97 " ",
98 ],
99 );
100 }
101
102 #[test]
103 fn scrolling_behaves_as_bottom_if_lines_overflow() {
104 assert_rendered(
105 "word word2 word3 word4",
106 size_for(&FONT_6X9, 5, 2),
107 &[
108 "..............................",
109 "......................#..####.",
110 "......................#....#..",
111 "#...#...##...#.#....###...##..",
112 "#.#.#..#..#..##.#..#..#.....#.",
113 "#.#.#..#..#..#.....#..#.....#.",
114 ".#.#....##...#......###..###..",
115 "..............................",
116 "..............................",
117 "..............................",
118 "......................#....#..",
119 "......................#...##..",
120 "#...#...##...#.#....###..#.#..",
121 "#.#.#..#..#..##.#..#..#.#..#..",
122 "#.#.#..#..#..#.....#..#.#####.",
123 ".#.#....##...#......###....#..",
124 "..............................",
125 "..............................",
126 ],
127 );
128 }
129}