1use super::{blend_mode, Blend, Coord, Rgb24, Size};
2use crate::col_modify::ColModify;
3use crate::context::*;
4use crate::view_cell::*;
5
6fn set_cell_relative_to_draw<F: ?Sized + Frame, C: ColModify>(
7 frame: &mut F,
8 relative_coord: Coord,
9 relative_depth: i8,
10 relative_cell: ViewCell,
11 context: ViewContext<C>,
12) {
13 if relative_coord.is_valid(context.size) {
14 let absolute_coord = relative_coord + context.offset;
15 let absolute_depth = relative_depth + context.depth;
16 let absolute_cell = ViewCell {
17 style: Style {
18 foreground: context
19 .col_modify
20 .foreground(relative_cell.style.foreground),
21 background: context
22 .col_modify
23 .background(relative_cell.style.background),
24 ..relative_cell.style
25 },
26 ..relative_cell
27 };
28 frame.set_cell_absolute(absolute_coord, absolute_depth, absolute_cell);
29 }
30}
31
32fn blend_cell_background_relative_to_draw<F: ?Sized + Frame, C: ColModify, B: Blend>(
33 frame: &mut F,
34 relative_coord: Coord,
35 relative_depth: i8,
36 rgb24: Rgb24,
37 alpha: u8,
38 blend: B,
39 context: ViewContext<C>,
40) {
41 if relative_coord.is_valid(context.size) {
42 let absolute_coord = relative_coord + context.offset;
43 let absolute_depth = relative_depth + context.depth;
44 if let Some(modified_rgb24) = context.col_modify.background(Some(rgb24)) {
45 frame.blend_cell_background_absolute(
46 absolute_coord,
47 absolute_depth,
48 modified_rgb24,
49 alpha,
50 blend,
51 );
52 }
53 }
54}
55
56fn set_cell_relative_to_measure_size<F: ?Sized + Frame, C: ColModify>(
57 frame: &mut F,
58 relative_coord: Coord,
59 context: ViewContext<C>,
60) {
61 if relative_coord.is_valid(context.size) {
62 let absolute_coord = relative_coord + context.offset;
63 const DEFAULT_CELL: ViewCell = ViewCell::new();
64 frame.set_cell_absolute(absolute_coord, 0, DEFAULT_CELL);
65 }
66}
67
68fn blend_cell_background_relative_to_measure_size<F: ?Sized + Frame, C: ColModify>(
69 frame: &mut F,
70 relative_coord: Coord,
71 context: ViewContext<C>,
72) {
73 if relative_coord.is_valid(context.size) {
74 let absolute_coord = relative_coord + context.offset;
75 frame.blend_cell_background_absolute(
76 absolute_coord,
77 0,
78 Rgb24::new(0, 0, 0),
79 0,
80 blend_mode::Replace,
81 );
82 }
83}
84
85pub trait Frame {
86 fn set_cell_relative<C: ColModify>(
87 &mut self,
88 relative_coord: Coord,
89 relative_depth: i8,
90 relative_cell: ViewCell,
91 context: ViewContext<C>,
92 ) {
93 set_cell_relative_to_draw(self, relative_coord, relative_depth, relative_cell, context);
94 }
95 fn set_cell_absolute(
96 &mut self,
97 absolute_coord: Coord,
98 absolute_depth: i8,
99 absolute_cell: ViewCell,
100 );
101 fn blend_cell_background_relative<C: ColModify, B: Blend>(
102 &mut self,
103 relative_coord: Coord,
104 relative_depth: i8,
105 rgb24: Rgb24,
106 alpha: u8,
107 blend: B,
108 context: ViewContext<C>,
109 ) {
110 blend_cell_background_relative_to_draw(
111 self,
112 relative_coord,
113 relative_depth,
114 rgb24,
115 alpha,
116 blend,
117 context,
118 );
119 }
120 fn blend_cell_background_absolute<B: Blend>(
121 &mut self,
122 absolute_coord: Coord,
123 absolute_depth: i8,
124 rgb24: Rgb24,
125 alpha: u8,
126 blend: B,
127 );
128}
129
130struct MeasureBounds {
131 max_absolute_coord: Coord,
132}
133
134impl MeasureBounds {
135 fn new() -> Self {
136 Self {
137 max_absolute_coord: Coord::new(0, 0),
138 }
139 }
140 fn size(&self, offset: Coord) -> Size {
141 (self.max_absolute_coord - offset)
142 .to_size()
143 .unwrap_or_else(|coord_2d::NegativeDimension| Size::new(0, 0))
144 + Size::new(1, 1)
145 }
146 fn set_max(&mut self, coord: Coord) {
147 self.max_absolute_coord.x = self.max_absolute_coord.x.max(coord.x);
148 self.max_absolute_coord.y = self.max_absolute_coord.y.max(coord.y);
149 }
150}
151
152impl Frame for MeasureBounds {
153 fn set_cell_relative<C: ColModify>(
154 &mut self,
155 relative_coord: Coord,
156 _relative_depth: i8,
157 _relative_cell: ViewCell,
158 context: ViewContext<C>,
159 ) {
160 set_cell_relative_to_measure_size(self, relative_coord, context);
161 }
162 fn set_cell_absolute(
163 &mut self,
164 absolute_coord: Coord,
165 _absolute_depth: i8,
166 _absolute_cell: ViewCell,
167 ) {
168 self.set_max(absolute_coord);
169 }
170 fn blend_cell_background_relative<C: ColModify, B: Blend>(
171 &mut self,
172 relative_coord: Coord,
173 _relative_depth: i8,
174 _rgb24: Rgb24,
175 _alpha: u8,
176 _blend: B,
177 context: ViewContext<C>,
178 ) {
179 blend_cell_background_relative_to_measure_size(self, relative_coord, context);
180 }
181 fn blend_cell_background_absolute<B: Blend>(
182 &mut self,
183 absolute_coord: Coord,
184 _absolute_depth: i8,
185 _rgb24: Rgb24,
186 _alpha: u8,
187 _blend: B,
188 ) {
189 self.set_max(absolute_coord);
190 }
191}
192
193pub struct MeasureBoundsAndDraw<'a, D> {
194 draw: &'a mut D,
195 measure_bounds: MeasureBounds,
196}
197
198impl<'a, D> MeasureBoundsAndDraw<'a, D>
199where
200 D: Frame,
201{
202 pub fn new(draw: &'a mut D) -> Self {
203 Self {
204 draw,
205 measure_bounds: MeasureBounds::new(),
206 }
207 }
208 fn size(&self, offset: Coord) -> Size {
209 self.measure_bounds.size(offset)
210 }
211}
212
213pub fn measure_size<V, T, C>(view: &mut V, data: T, context: ViewContext<C>) -> Size
214where
215 V: View<T> + ?Sized,
216 C: ColModify,
217{
218 let mut measure_bounds = MeasureBounds::new();
219 view.view(data, context, &mut measure_bounds);
220 measure_bounds.size(context.offset)
221}
222
223pub fn measure_size_and_draw<V, T, C, F>(
224 view: &mut V,
225 data: T,
226 context: ViewContext<C>,
227 frame: &mut F,
228) -> Size
229where
230 V: View<T> + ?Sized,
231 C: ColModify,
232 F: Frame,
233{
234 let mut measure_bounds_and_draw = MeasureBoundsAndDraw::new(frame);
235 view.view(data, context, &mut measure_bounds_and_draw);
236 measure_bounds_and_draw.size(context.offset)
237}
238
239impl<'a, D> Frame for MeasureBoundsAndDraw<'a, D>
240where
241 D: Frame,
242{
243 fn set_cell_relative<C: ColModify>(
244 &mut self,
245 relative_coord: Coord,
246 relative_depth: i8,
247 relative_cell: ViewCell,
248 context: ViewContext<C>,
249 ) {
250 self.draw
251 .set_cell_relative(relative_coord, relative_depth, relative_cell, context);
252 self.measure_bounds.set_cell_relative(
253 relative_coord,
254 relative_depth,
255 relative_cell,
256 context,
257 );
258 }
259 fn set_cell_absolute(
260 &mut self,
261 absolute_coord: Coord,
262 absolute_depth: i8,
263 absolute_cell: ViewCell,
264 ) {
265 self.draw
266 .set_cell_absolute(absolute_coord, absolute_depth, absolute_cell);
267 self.measure_bounds
268 .set_cell_absolute(absolute_coord, absolute_depth, absolute_cell);
269 }
270 fn blend_cell_background_relative<C: ColModify, B: Blend>(
271 &mut self,
272 relative_coord: Coord,
273 relative_depth: i8,
274 rgb24: Rgb24,
275 alpha: u8,
276 blend: B,
277 context: ViewContext<C>,
278 ) {
279 self.draw.blend_cell_background_relative(
280 relative_coord,
281 relative_depth,
282 rgb24,
283 alpha,
284 blend,
285 context,
286 );
287 self.measure_bounds.blend_cell_background_relative(
288 relative_coord,
289 relative_depth,
290 rgb24,
291 alpha,
292 blend,
293 context,
294 );
295 }
296 fn blend_cell_background_absolute<B: Blend>(
297 &mut self,
298 absolute_coord: Coord,
299 absolute_depth: i8,
300 rgb24: Rgb24,
301 alpha: u8,
302 blend: B,
303 ) {
304 self.draw.blend_cell_background_absolute(
305 absolute_coord,
306 absolute_depth,
307 rgb24,
308 alpha,
309 blend,
310 );
311 self.measure_bounds.blend_cell_background_absolute(
312 absolute_coord,
313 absolute_depth,
314 rgb24,
315 alpha,
316 blend,
317 );
318 }
319}
320
321pub trait View<T> {
322 fn view<F: Frame, C: ColModify>(&mut self, data: T, context: ViewContext<C>, frame: &mut F);
323
324 fn size<C: ColModify>(&mut self, data: T, context: ViewContext<C>) -> Size {
325 measure_size(self, data, context)
326 }
327
328 fn view_size<F: Frame, C: ColModify>(
329 &mut self,
330 data: T,
331 context: ViewContext<C>,
332 frame: &mut F,
333 ) -> Size {
334 measure_size_and_draw(self, data, context, frame)
335 }
336}
337
338impl<'a, T, V: View<T>> View<T> for &'a mut V {
339 fn view<F: Frame, C: ColModify>(&mut self, data: T, context: ViewContext<C>, frame: &mut F) {
340 (*self).view(data, context, frame)
341 }
342 fn size<C: ColModify>(&mut self, data: T, context: ViewContext<C>) -> Size {
343 (*self).size(data, context)
344 }
345 fn view_size<F: Frame, C: ColModify>(
346 &mut self,
347 data: T,
348 context: ViewContext<C>,
349 frame: &mut F,
350 ) -> Size {
351 (*self).view_size(data, context, frame)
352 }
353}