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