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 state: &mut Tree,
439 layout: Layout<'_>,
440 renderer: &Renderer,
441 operation: &mut dyn widget::Operation,
442 ) {
443 self.element
444 .widget
445 .operate(state, layout, renderer, operation);
446 }
447
448 fn update(
449 &mut self,
450 state: &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 state, event, layout, cursor, renderer, clipboard, shell, viewport,
461 );
462 }
463
464 fn draw(
465 &self,
466 state: &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(state, renderer, theme, style, layout, cursor, viewport);
500
501 explain_layout(renderer, self.color, layout);
502 }
503
504 fn mouse_interaction(
505 &self,
506 state: &Tree,
507 layout: Layout<'_>,
508 cursor: mouse::Cursor,
509 viewport: &Rectangle,
510 renderer: &Renderer,
511 ) -> mouse::Interaction {
512 self.element
513 .widget
514 .mouse_interaction(state, layout, cursor, viewport, renderer)
515 }
516
517 fn overlay<'b>(
518 &'b mut self,
519 state: &'b mut Tree,
520 layout: Layout<'b>,
521 renderer: &Renderer,
522 viewport: &Rectangle,
523 translation: Vector,
524 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
525 self.element.widget.overlay(
526 state,
527 layout,
528 renderer,
529 viewport,
530 translation,
531 )
532 }
533}
534
535impl<'a, T, Message, Theme, Renderer> From<Option<T>>
536 for Element<'a, Message, Theme, Renderer>
537where
538 T: Into<Self>,
539 Renderer: crate::Renderer,
540{
541 fn from(element: Option<T>) -> Self {
542 struct Void;
543
544 impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Void
545 where
546 Renderer: crate::Renderer,
547 {
548 fn size(&self) -> Size<Length> {
549 Size {
550 width: Length::Fixed(0.0),
551 height: Length::Fixed(0.0),
552 }
553 }
554
555 fn layout(
556 &mut self,
557 _tree: &mut Tree,
558 _renderer: &Renderer,
559 _limits: &layout::Limits,
560 ) -> layout::Node {
561 layout::Node::new(Size::ZERO)
562 }
563
564 fn draw(
565 &self,
566 _tree: &Tree,
567 _renderer: &mut Renderer,
568 _theme: &Theme,
569 _style: &renderer::Style,
570 _layout: Layout<'_>,
571 _cursor: mouse::Cursor,
572 _viewport: &Rectangle,
573 ) {
574 }
575 }
576
577 element.map(T::into).unwrap_or_else(|| Element::new(Void))
578 }
579}