microbit_text/
scrolling_text.rs

1//! Support for scrolling ascii text horizontally.
2//!
3//! # Example
4//!
5//! ```ignore
6//! use microbit::display::nonblocking::{Display, Frame, MicrobitFrame};
7//! use microbit_text::scrolling::Animate;
8//! use microbit_text::scrolling_text::ScrollingStaticText;
9//! let mut display = MicrobitDisplay::new(...);
10//! let mut scroller = ScrollingStaticText::default();
11//! let frame = MicrobitFrame::default();
12//! scroller.set_message(b"Hello, world!");
13//! while !scroller.is_finished() {
14//!     // every 50ms or so
15//!     scroller.tick();
16//!     frame.set(scroller);
17//!     display.show_frame(frame);
18//! }
19//! ```
20//!
21
22use tiny_led_matrix::Render;
23
24use crate::image::BitImage;
25use crate::font;
26use crate::scrolling::{Animate, ScrollingState, Scrollable};
27
28/// A [`Scrollable`] displaying a static ascii byte-string slice.
29#[derive(Default)]
30#[derive(Copy, Clone)]
31pub struct ScrollingStaticText {
32    message: &'static [u8],
33    state: ScrollingState,
34}
35
36impl ScrollingStaticText {
37
38    /// Specifies the ascii byte-string slice to be displayed.
39    ///
40    /// This also resets the animation to the beginning.
41    pub fn set_message(&mut self, message: &'static [u8]) {
42        self.message = message;
43        self.reset();
44    }
45
46}
47
48impl Scrollable for ScrollingStaticText {
49
50    type Subimage = BitImage;
51
52    fn length(&self) -> usize {
53        self.message.len()
54    }
55
56    fn state(&self) -> &ScrollingState {
57        &self.state
58    }
59
60    fn state_mut(&mut self) -> &mut ScrollingState {
61        &mut self.state
62    }
63
64    fn subimage(&self, index: usize) -> &BitImage {
65        font::character(self.message[index])
66    }
67
68}
69
70
71impl Render for ScrollingStaticText {
72
73    fn brightness_at(&self, x: usize, y: usize) -> u8 {
74        self.current_brightness_at(x, y)
75    }
76
77}
78
79
80/// A [`Scrollable`] displaying an ascii byte-string of up to `N` bytes.
81#[derive(Copy, Clone)]
82pub struct ScrollingBufferedText<const N: usize> {
83    length: usize,
84    message: [u8; N],
85    state: ScrollingState,
86}
87
88impl<const N: usize> ScrollingBufferedText<N> {
89
90    /// Specifies the ascii byte-string to be displayed.
91    ///
92    /// Makes a copy of the byte-string.
93    ///
94    /// This also resets the animation to the beginning.
95    ///
96    /// # Panics
97    ///
98    /// Panics if `message` is more than `N` bytes long.
99    pub fn set_message(&mut self, message: &[u8]) {
100        assert!(message.len() <= N, "message too long");
101        self.length = message.len();
102        self.message[..self.length].copy_from_slice(message);
103        self.reset();
104    }
105
106
107}
108
109impl<const N: usize> Default for ScrollingBufferedText<N> {
110
111    fn default() -> ScrollingBufferedText<N> {
112        ScrollingBufferedText {
113            length: 0,
114            message: [0; N],
115            state: Default::default(),
116        }
117    }
118
119}
120
121impl<const N: usize> Scrollable for ScrollingBufferedText<N> {
122
123    type Subimage = BitImage;
124
125    fn length(&self) -> usize {
126        self.length
127    }
128
129    fn state(&self) -> &ScrollingState {
130        &self.state
131    }
132
133    fn state_mut(&mut self) -> &mut ScrollingState {
134        &mut self.state
135    }
136
137    fn subimage(&self, index: usize) -> &BitImage {
138        font::character(self.message[index])
139    }
140
141}
142
143impl<const N: usize> Render for ScrollingBufferedText<N> {
144
145    fn brightness_at(&self, x: usize, y: usize) -> u8 {
146        self.current_brightness_at(x, y)
147    }
148
149}
150