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