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