1use crate::layout;
2use crate::mouse;
3use crate::overlay;
4use crate::renderer;
5use crate::widget;
6use crate::widget::tree::{self, Tree};
7use crate::{Border, Color, Event, Layout, Length, Rectangle, Shell, Size, Vector, Widget};
8
9use std::borrow::Borrow;
10
11pub struct Element<'a, Message, Theme, Renderer> {
21 widget: Box<dyn Widget<Message, Theme, Renderer> + 'a>,
22}
23
24impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
25 pub fn new(widget: impl Widget<Message, Theme, Renderer> + 'a) -> Self
27 where
28 Renderer: crate::Renderer,
29 {
30 Self {
31 widget: Box::new(widget),
32 }
33 }
34
35 pub fn as_widget(&self) -> &dyn Widget<Message, Theme, Renderer> {
37 self.widget.as_ref()
38 }
39
40 pub fn as_widget_mut(&mut self) -> &mut dyn Widget<Message, Theme, Renderer> {
42 self.widget.as_mut()
43 }
44
45 pub fn map<B>(self, f: impl Fn(Message) -> B + 'a) -> Element<'a, B, Theme, Renderer>
185 where
186 Message: 'a,
187 Theme: 'a,
188 Renderer: crate::Renderer + 'a,
189 B: 'a,
190 {
191 Element::new(Map::new(self.widget, f))
192 }
193
194 pub fn explain<C: Into<Color>>(self, color: C) -> Element<'a, Message, Theme, Renderer>
201 where
202 Message: 'a,
203 Theme: 'a,
204 Renderer: crate::Renderer + 'a,
205 {
206 Element {
207 widget: Box::new(Explain::new(self, color.into())),
208 }
209 }
210}
211
212impl<'a, Message, Theme, Renderer> Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
213 for Element<'a, Message, Theme, Renderer>
214{
215 fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
216 self.widget.borrow()
217 }
218}
219
220impl<'a, Message, Theme, Renderer> Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
221 for &Element<'a, Message, Theme, Renderer>
222{
223 fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
224 self.widget.borrow()
225 }
226}
227
228struct Map<'a, A, B, Theme, Renderer> {
229 widget: Box<dyn Widget<A, Theme, Renderer> + 'a>,
230 mapper: Box<dyn Fn(A) -> B + 'a>,
231}
232
233impl<'a, A, B, Theme, Renderer> Map<'a, A, B, Theme, Renderer> {
234 pub fn new<F>(
235 widget: Box<dyn Widget<A, Theme, Renderer> + 'a>,
236 mapper: F,
237 ) -> Map<'a, A, B, Theme, Renderer>
238 where
239 F: 'a + Fn(A) -> B,
240 {
241 Map {
242 widget,
243 mapper: Box::new(mapper),
244 }
245 }
246}
247
248impl<'a, A, B, Theme, Renderer> Widget<B, Theme, Renderer> for Map<'a, A, B, Theme, Renderer>
249where
250 Renderer: crate::Renderer + 'a,
251 A: 'a,
252 B: 'a,
253{
254 fn tag(&self) -> tree::Tag {
255 self.widget.tag()
256 }
257
258 fn state(&self) -> tree::State {
259 self.widget.state()
260 }
261
262 fn children(&self) -> Vec<Tree> {
263 self.widget.children()
264 }
265
266 fn diff(&self, tree: &mut Tree) {
267 self.widget.diff(tree);
268 }
269
270 fn size(&self) -> Size<Length> {
271 self.widget.size()
272 }
273
274 fn size_hint(&self) -> Size<Length> {
275 self.widget.size_hint()
276 }
277
278 fn layout(
279 &mut self,
280 tree: &mut Tree,
281 renderer: &Renderer,
282 limits: &layout::Limits,
283 ) -> layout::Node {
284 self.widget.layout(tree, renderer, limits)
285 }
286
287 fn operate(
288 &mut self,
289 tree: &mut Tree,
290 layout: Layout<'_>,
291 renderer: &Renderer,
292 operation: &mut dyn widget::Operation,
293 ) {
294 self.widget.operate(tree, layout, renderer, operation);
295 }
296
297 fn update(
298 &mut self,
299 tree: &mut Tree,
300 event: &Event,
301 layout: Layout<'_>,
302 cursor: mouse::Cursor,
303 renderer: &Renderer,
304 shell: &mut Shell<'_, B>,
305 viewport: &Rectangle,
306 ) {
307 let mut local_messages = Vec::new();
308 let mut local_shell = Shell::new(&mut local_messages);
309
310 self.widget.update(
311 tree,
312 event,
313 layout,
314 cursor,
315 renderer,
316 &mut local_shell,
317 viewport,
318 );
319
320 shell.merge(local_shell, &self.mapper);
321 }
322
323 fn draw(
324 &self,
325 tree: &Tree,
326 renderer: &mut Renderer,
327 theme: &Theme,
328 style: &renderer::Style,
329 layout: Layout<'_>,
330 cursor: mouse::Cursor,
331 viewport: &Rectangle,
332 ) {
333 self.widget
334 .draw(tree, renderer, theme, style, layout, cursor, viewport);
335 }
336
337 fn mouse_interaction(
338 &self,
339 tree: &Tree,
340 layout: Layout<'_>,
341 cursor: mouse::Cursor,
342 viewport: &Rectangle,
343 renderer: &Renderer,
344 ) -> mouse::Interaction {
345 self.widget
346 .mouse_interaction(tree, layout, cursor, viewport, renderer)
347 }
348
349 fn overlay<'b>(
350 &'b mut self,
351 tree: &'b mut Tree,
352 layout: Layout<'b>,
353 renderer: &Renderer,
354 viewport: &Rectangle,
355 translation: Vector,
356 ) -> Option<overlay::Element<'b, B, Theme, Renderer>> {
357 let mapper = &self.mapper;
358
359 self.widget
360 .overlay(tree, layout, renderer, viewport, translation)
361 .map(move |overlay| overlay.map(mapper))
362 }
363}
364
365struct Explain<'a, Message, Theme, Renderer: crate::Renderer> {
366 element: Element<'a, Message, Theme, Renderer>,
367 color: Color,
368}
369
370impl<'a, Message, Theme, Renderer> Explain<'a, Message, Theme, Renderer>
371where
372 Renderer: crate::Renderer,
373{
374 fn new(element: Element<'a, Message, Theme, Renderer>, color: Color) -> Self {
375 Explain { element, color }
376 }
377}
378
379impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
380 for Explain<'_, Message, Theme, Renderer>
381where
382 Renderer: crate::Renderer,
383{
384 fn size(&self) -> Size<Length> {
385 self.element.widget.size()
386 }
387
388 fn size_hint(&self) -> Size<Length> {
389 self.element.widget.size_hint()
390 }
391
392 fn tag(&self) -> tree::Tag {
393 self.element.widget.tag()
394 }
395
396 fn state(&self) -> tree::State {
397 self.element.widget.state()
398 }
399
400 fn children(&self) -> Vec<Tree> {
401 self.element.widget.children()
402 }
403
404 fn diff(&self, tree: &mut Tree) {
405 self.element.widget.diff(tree);
406 }
407
408 fn layout(
409 &mut self,
410 tree: &mut Tree,
411 renderer: &Renderer,
412 limits: &layout::Limits,
413 ) -> layout::Node {
414 self.element.widget.layout(tree, renderer, limits)
415 }
416
417 fn operate(
418 &mut self,
419 tree: &mut Tree,
420 layout: Layout<'_>,
421 renderer: &Renderer,
422 operation: &mut dyn widget::Operation,
423 ) {
424 self.element
425 .widget
426 .operate(tree, layout, renderer, operation);
427 }
428
429 fn update(
430 &mut self,
431 tree: &mut Tree,
432 event: &Event,
433 layout: Layout<'_>,
434 cursor: mouse::Cursor,
435 renderer: &Renderer,
436 shell: &mut Shell<'_, Message>,
437 viewport: &Rectangle,
438 ) {
439 self.element
440 .widget
441 .update(tree, event, layout, cursor, renderer, shell, viewport);
442 }
443
444 fn draw(
445 &self,
446 tree: &Tree,
447 renderer: &mut Renderer,
448 theme: &Theme,
449 style: &renderer::Style,
450 layout: Layout<'_>,
451 cursor: mouse::Cursor,
452 viewport: &Rectangle,
453 ) {
454 fn explain_layout<Renderer: crate::Renderer>(
455 renderer: &mut Renderer,
456 color: Color,
457 layout: Layout<'_>,
458 ) {
459 renderer.fill_quad(
460 renderer::Quad {
461 bounds: layout.bounds(),
462 border: Border {
463 color,
464 width: 1.0,
465 ..Border::default()
466 },
467 ..renderer::Quad::default()
468 },
469 Color::TRANSPARENT,
470 );
471
472 for child in layout.children() {
473 explain_layout(renderer, color, child);
474 }
475 }
476
477 self.element
478 .widget
479 .draw(tree, renderer, theme, style, layout, cursor, viewport);
480
481 renderer.with_layer(Rectangle::INFINITE, |renderer| {
482 explain_layout(renderer, self.color, layout);
483 });
484 }
485
486 fn mouse_interaction(
487 &self,
488 tree: &Tree,
489 layout: Layout<'_>,
490 cursor: mouse::Cursor,
491 viewport: &Rectangle,
492 renderer: &Renderer,
493 ) -> mouse::Interaction {
494 self.element
495 .widget
496 .mouse_interaction(tree, layout, cursor, viewport, renderer)
497 }
498
499 fn overlay<'b>(
500 &'b mut self,
501 tree: &'b mut Tree,
502 layout: Layout<'b>,
503 renderer: &Renderer,
504 viewport: &Rectangle,
505 translation: Vector,
506 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
507 self.element
508 .widget
509 .overlay(tree, layout, renderer, viewport, translation)
510 }
511}
512
513impl<'a, T, Message, Theme, Renderer> From<Option<T>> for Element<'a, Message, Theme, Renderer>
514where
515 T: Into<Self>,
516 Renderer: crate::Renderer,
517{
518 fn from(element: Option<T>) -> Self {
519 struct Void;
520
521 impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Void
522 where
523 Renderer: crate::Renderer,
524 {
525 fn size(&self) -> Size<Length> {
526 Size {
527 width: Length::Fixed(0.0),
528 height: Length::Fixed(0.0),
529 }
530 }
531
532 fn layout(
533 &mut self,
534 _tree: &mut Tree,
535 _renderer: &Renderer,
536 _limits: &layout::Limits,
537 ) -> layout::Node {
538 layout::Node::new(Size::ZERO)
539 }
540
541 fn draw(
542 &self,
543 _tree: &Tree,
544 _renderer: &mut Renderer,
545 _theme: &Theme,
546 _style: &renderer::Style,
547 _layout: Layout<'_>,
548 _cursor: mouse::Cursor,
549 _viewport: &Rectangle,
550 ) {
551 }
552 }
553
554 element.map(T::into).unwrap_or_else(|| Element::new(Void))
555 }
556}