1use embedded_graphics::{
4 draw_target::DrawTarget,
5 prelude::PixelColor,
6 primitives::Rectangle,
7 text::renderer::{CharacterStyle, TextRenderer},
8};
9use object_chain::{Chain, ChainElement, Link};
10
11use crate::{
12 parser::Token,
13 rendering::{cursor::Cursor, TextBoxProperties},
14};
15
16pub trait Plugin<'a, C>: Clone
25where
26 C: PixelColor,
27{
28 #[inline]
30 fn new_line(&mut self) {}
31
32 #[inline]
34 fn next_token(
35 &mut self,
36 mut next_token: impl FnMut() -> Option<Token<'a, C>>,
37 ) -> Option<Token<'a, C>> {
38 next_token()
39 }
40
41 #[inline]
46 fn render_token(&mut self, token: Token<'a, C>) -> Option<Token<'a, C>> {
47 Some(token)
48 }
49
50 #[inline]
52 fn post_render<T, D>(
53 &mut self,
54 _draw_target: &mut D,
55 _character_style: &T,
56 _text: Option<&str>,
57 _bounds: Rectangle,
58 ) -> Result<(), D::Error>
59 where
60 T: TextRenderer<Color = C>,
61 D: DrawTarget<Color = C>,
62 {
63 Ok(())
64 }
65
66 #[inline]
68 fn on_start_render<S: CharacterStyle + TextRenderer>(
69 &mut self,
70 _cursor: &mut Cursor,
71 _props: &TextBoxProperties<'_, S>,
72 ) {
73 }
74
75 #[inline]
77 fn on_rendering_finished(&mut self) {}
78}
79
80impl<'a, C> Plugin<'a, C> for super::NoPlugin<C> where C: PixelColor {}
81
82impl<'a, C, P> Plugin<'a, C> for Chain<P>
83where
84 P: Plugin<'a, C>,
85 C: PixelColor,
86 Chain<P>: Clone,
87{
88 fn new_line(&mut self) {
89 self.object.new_line();
90 }
91
92 fn next_token(
93 &mut self,
94 next_token: impl FnMut() -> Option<Token<'a, C>>,
95 ) -> Option<Token<'a, C>> {
96 self.object.next_token(next_token)
97 }
98
99 fn render_token(&mut self, token: Token<'a, C>) -> Option<Token<'a, C>> {
100 self.object.render_token(token)
101 }
102
103 fn post_render<T, D>(
104 &mut self,
105 draw_target: &mut D,
106 character_style: &T,
107 text: Option<&str>,
108 bounds: Rectangle,
109 ) -> Result<(), D::Error>
110 where
111 T: TextRenderer<Color = C>,
112 D: DrawTarget<Color = C>,
113 {
114 self.object
115 .post_render(draw_target, character_style, text, bounds)
116 }
117
118 fn on_start_render<S: CharacterStyle + TextRenderer>(
119 &mut self,
120 cursor: &mut Cursor,
121 props: &TextBoxProperties<'_, S>,
122 ) {
123 self.object.on_start_render(cursor, props);
124 }
125
126 fn on_rendering_finished(&mut self) {
127 self.object.on_rendering_finished();
128 }
129}
130
131impl<'a, C, P, CE> Plugin<'a, C> for Link<P, CE>
132where
133 CE: ChainElement + Plugin<'a, C>,
134 P: Plugin<'a, C>,
135 C: PixelColor,
136 Link<P, CE>: Clone,
137{
138 fn new_line(&mut self) {
139 self.parent.new_line();
140 self.object.new_line();
141 }
142
143 fn next_token(
144 &mut self,
145 mut next_token: impl FnMut() -> Option<Token<'a, C>>,
146 ) -> Option<Token<'a, C>> {
147 let parent = &mut self.parent;
148 let next_token = || parent.next_token(&mut next_token);
149 self.object.next_token(next_token)
150 }
151
152 fn render_token(&mut self, token: Token<'a, C>) -> Option<Token<'a, C>> {
153 self.parent
154 .render_token(token)
155 .and_then(|t| self.object.render_token(t))
156 }
157
158 fn post_render<T, D>(
159 &mut self,
160 draw_target: &mut D,
161 character_style: &T,
162 text: Option<&str>,
163 bounds: Rectangle,
164 ) -> Result<(), D::Error>
165 where
166 T: TextRenderer<Color = C>,
167 D: DrawTarget<Color = C>,
168 {
169 self.parent
170 .post_render(draw_target, character_style, text, bounds)?;
171 self.object
172 .post_render(draw_target, character_style, text, bounds)
173 }
174
175 fn on_start_render<S: CharacterStyle + TextRenderer>(
176 &mut self,
177 cursor: &mut Cursor,
178 props: &TextBoxProperties<'_, S>,
179 ) {
180 self.parent.on_start_render(cursor, props);
181 self.object.on_start_render(cursor, props);
182 }
183
184 fn on_rendering_finished(&mut self) {
185 self.parent.on_rendering_finished();
186 self.object.on_rendering_finished();
187 }
188}