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.col_modify.foreground(relative_cell.style.foreground),
19 background: context.col_modify.background(relative_cell.style.background),
20 ..relative_cell.style
21 },
22 ..relative_cell
23 };
24 frame.set_cell_absolute(absolute_coord, absolute_depth, absolute_cell);
25 }
26}
27
28fn blend_cell_background_relative_to_draw<F: ?Sized + Frame, C: ColModify, B: Blend>(
29 frame: &mut F,
30 relative_coord: Coord,
31 relative_depth: i8,
32 rgb24: Rgb24,
33 alpha: u8,
34 blend: B,
35 context: ViewContext<C>,
36) {
37 if relative_coord.is_valid(context.size) {
38 let absolute_coord = relative_coord + context.offset;
39 let absolute_depth = relative_depth + context.depth;
40 if let Some(modified_rgb24) = context.col_modify.background(Some(rgb24)) {
41 frame.blend_cell_background_absolute(absolute_coord, absolute_depth, modified_rgb24, alpha, blend);
42 }
43 }
44}
45
46fn set_cell_relative_to_measure_size<F: ?Sized + Frame, C: ColModify>(
47 frame: &mut F,
48 relative_coord: Coord,
49 context: ViewContext<C>,
50) {
51 if relative_coord.is_valid(context.size) {
52 let absolute_coord = relative_coord + context.offset;
53 const DEFAULT_CELL: ViewCell = ViewCell::new();
54 frame.set_cell_absolute(absolute_coord, 0, DEFAULT_CELL);
55 }
56}
57
58fn blend_cell_background_relative_to_measure_size<F: ?Sized + Frame, C: ColModify>(
59 frame: &mut F,
60 relative_coord: Coord,
61 context: ViewContext<C>,
62) {
63 if relative_coord.is_valid(context.size) {
64 let absolute_coord = relative_coord + context.offset;
65 frame.blend_cell_background_absolute(absolute_coord, 0, Rgb24::new(0, 0, 0), 0, blend_mode::Replace);
66 }
67}
68
69pub trait Frame {
70 fn set_cell_relative<C: ColModify>(
71 &mut self,
72 relative_coord: Coord,
73 relative_depth: i8,
74 relative_cell: ViewCell,
75 context: ViewContext<C>,
76 ) {
77 set_cell_relative_to_draw(self, relative_coord, relative_depth, relative_cell, context);
78 }
79 fn set_cell_absolute(&mut self, absolute_coord: Coord, absolute_depth: i8, absolute_cell: ViewCell);
80 fn blend_cell_background_relative<C: ColModify, B: Blend>(
81 &mut self,
82 relative_coord: Coord,
83 relative_depth: i8,
84 rgb24: Rgb24,
85 alpha: u8,
86 blend: B,
87 context: ViewContext<C>,
88 ) {
89 blend_cell_background_relative_to_draw(self, relative_coord, relative_depth, rgb24, alpha, blend, context);
90 }
91 fn blend_cell_background_absolute<B: Blend>(
92 &mut self,
93 absolute_coord: Coord,
94 absolute_depth: i8,
95 rgb24: Rgb24,
96 alpha: u8,
97 blend: B,
98 );
99}
100
101struct MeasureBounds {
102 max_absolute_coord: Coord,
103}
104
105impl MeasureBounds {
106 fn new() -> Self {
107 Self {
108 max_absolute_coord: Coord::new(0, 0),
109 }
110 }
111 fn size(&self, offset: Coord) -> Size {
112 (self.max_absolute_coord - offset)
113 .to_size()
114 .unwrap_or_else(|coord_2d::NegativeDimension| Size::new(0, 0))
115 + Size::new(1, 1)
116 }
117 fn set_max(&mut self, coord: Coord) {
118 self.max_absolute_coord.x = self.max_absolute_coord.x.max(coord.x);
119 self.max_absolute_coord.y = self.max_absolute_coord.y.max(coord.y);
120 }
121}
122
123impl Frame for MeasureBounds {
124 fn set_cell_relative<C: ColModify>(
125 &mut self,
126 relative_coord: Coord,
127 _relative_depth: i8,
128 _relative_cell: ViewCell,
129 context: ViewContext<C>,
130 ) {
131 set_cell_relative_to_measure_size(self, relative_coord, context);
132 }
133 fn set_cell_absolute(&mut self, absolute_coord: Coord, _absolute_depth: i8, _absolute_cell: ViewCell) {
134 self.set_max(absolute_coord);
135 }
136 fn blend_cell_background_relative<C: ColModify, B: Blend>(
137 &mut self,
138 relative_coord: Coord,
139 _relative_depth: i8,
140 _rgb24: Rgb24,
141 _alpha: u8,
142 _blend: B,
143 context: ViewContext<C>,
144 ) {
145 blend_cell_background_relative_to_measure_size(self, relative_coord, context);
146 }
147 fn blend_cell_background_absolute<B: Blend>(
148 &mut self,
149 absolute_coord: Coord,
150 _absolute_depth: i8,
151 _rgb24: Rgb24,
152 _alpha: u8,
153 _blend: B,
154 ) {
155 self.set_max(absolute_coord);
156 }
157}
158
159pub struct MeasureBoundsAndDraw<'a, D> {
160 draw: &'a mut D,
161 measure_bounds: MeasureBounds,
162}
163
164impl<'a, D> MeasureBoundsAndDraw<'a, D>
165where
166 D: Frame,
167{
168 pub fn new(draw: &'a mut D) -> Self {
169 Self {
170 draw,
171 measure_bounds: MeasureBounds::new(),
172 }
173 }
174 fn size(&self, offset: Coord) -> Size {
175 self.measure_bounds.size(offset)
176 }
177}
178
179pub fn measure_size<V, T, C>(view: &mut V, data: T, context: ViewContext<C>) -> Size
180where
181 V: View<T> + ?Sized,
182 C: ColModify,
183{
184 let mut measure_bounds = MeasureBounds::new();
185 view.view(data, context, &mut measure_bounds);
186 measure_bounds.size(context.offset)
187}
188
189pub fn measure_size_and_draw<V, T, C, F>(view: &mut V, data: T, context: ViewContext<C>, frame: &mut F) -> Size
190where
191 V: View<T> + ?Sized,
192 C: ColModify,
193 F: Frame,
194{
195 let mut measure_bounds_and_draw = MeasureBoundsAndDraw::new(frame);
196 view.view(data, context, &mut measure_bounds_and_draw);
197 measure_bounds_and_draw.size(context.offset)
198}
199
200impl<'a, D> Frame for MeasureBoundsAndDraw<'a, D>
201where
202 D: Frame,
203{
204 fn set_cell_relative<C: ColModify>(
205 &mut self,
206 relative_coord: Coord,
207 relative_depth: i8,
208 relative_cell: ViewCell,
209 context: ViewContext<C>,
210 ) {
211 self.draw
212 .set_cell_relative(relative_coord, relative_depth, relative_cell, context);
213 self.measure_bounds
214 .set_cell_relative(relative_coord, relative_depth, relative_cell, context);
215 }
216 fn set_cell_absolute(&mut self, absolute_coord: Coord, absolute_depth: i8, absolute_cell: ViewCell) {
217 self.draw
218 .set_cell_absolute(absolute_coord, absolute_depth, absolute_cell);
219 self.measure_bounds
220 .set_cell_absolute(absolute_coord, absolute_depth, absolute_cell);
221 }
222 fn blend_cell_background_relative<C: ColModify, B: Blend>(
223 &mut self,
224 relative_coord: Coord,
225 relative_depth: i8,
226 rgb24: Rgb24,
227 alpha: u8,
228 blend: B,
229 context: ViewContext<C>,
230 ) {
231 self.draw
232 .blend_cell_background_relative(relative_coord, relative_depth, rgb24, alpha, blend, context);
233 self.measure_bounds.blend_cell_background_relative(
234 relative_coord,
235 relative_depth,
236 rgb24,
237 alpha,
238 blend,
239 context,
240 );
241 }
242 fn blend_cell_background_absolute<B: Blend>(
243 &mut self,
244 absolute_coord: Coord,
245 absolute_depth: i8,
246 rgb24: Rgb24,
247 alpha: u8,
248 blend: B,
249 ) {
250 self.draw
251 .blend_cell_background_absolute(absolute_coord, absolute_depth, rgb24, alpha, blend);
252 self.measure_bounds
253 .blend_cell_background_absolute(absolute_coord, absolute_depth, rgb24, alpha, blend);
254 }
255}
256
257pub trait View<T> {
258 fn view<F: Frame, C: ColModify>(&mut self, data: T, context: ViewContext<C>, frame: &mut F);
259
260 fn size<C: ColModify>(&mut self, data: T, context: ViewContext<C>) -> Size {
261 measure_size(self, data, context)
262 }
263
264 fn view_size<F: Frame, C: ColModify>(&mut self, data: T, context: ViewContext<C>, frame: &mut F) -> Size {
265 measure_size_and_draw(self, data, context, frame)
266 }
267}
268
269impl<'a, T, V: View<T>> View<T> for &'a mut V {
270 fn view<F: Frame, C: ColModify>(&mut self, data: T, context: ViewContext<C>, frame: &mut F) {
271 (*self).view(data, context, frame)
272 }
273 fn size<C: ColModify>(&mut self, data: T, context: ViewContext<C>) -> Size {
274 (*self).size(data, context)
275 }
276 fn view_size<F: Frame, C: ColModify>(&mut self, data: T, context: ViewContext<C>, frame: &mut F) -> Size {
277 (*self).view_size(data, context, frame)
278 }
279}