iced_core/
element.rs

1use crate::event::{self, Event};
2use crate::id::Id;
3use crate::layout;
4use crate::mouse;
5use crate::overlay;
6use crate::renderer;
7use crate::widget;
8use crate::widget::tree::{self, Tree};
9use crate::{
10    Border, Clipboard, Color, Layout, Length, Rectangle, Shell, Size, Vector,
11    Widget,
12};
13
14use std::borrow::{Borrow, BorrowMut};
15
16/// A generic [`Widget`].
17///
18/// It is useful to build composable user interfaces that do not leak
19/// implementation details in their __view logic__.
20///
21/// If you have a [built-in widget], you should be able to use `Into<Element>`
22/// to turn it into an [`Element`].
23///
24/// [built-in widget]: crate::widget
25#[allow(missing_debug_implementations)]
26pub struct Element<'a, Message, Theme, Renderer> {
27    widget: Box<dyn Widget<Message, Theme, Renderer> + 'a>,
28}
29
30impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
31    /// Creates a new [`Element`] containing the given [`Widget`].
32    pub fn new(widget: impl Widget<Message, Theme, Renderer> + 'a) -> Self
33    where
34        Renderer: crate::Renderer,
35    {
36        Self {
37            widget: Box::new(widget),
38        }
39    }
40
41    /// Returns a reference to the [`Widget`] of the [`Element`],
42    pub fn as_widget(&self) -> &dyn Widget<Message, Theme, Renderer> {
43        self.widget.as_ref()
44    }
45
46    /// Returns a mutable reference to the [`Widget`] of the [`Element`],
47    pub fn as_widget_mut(
48        &mut self,
49    ) -> &mut dyn Widget<Message, Theme, Renderer> {
50        self.widget.as_mut()
51    }
52
53    /// Applies a transformation to the produced message of the [`Element`].
54    ///
55    /// This method is useful when you want to decouple different parts of your
56    /// UI and make them __composable__.
57    ///
58    /// # Example
59    /// Imagine we want to use [our counter](index.html#usage). But instead of
60    /// showing a single counter, we want to display many of them. We can reuse
61    /// the `Counter` type as it is!
62    ///
63    /// We use composition to model the __state__ of our new application:
64    ///
65    /// ```
66    /// # mod counter {
67    /// #     pub struct Counter;
68    /// # }
69    /// use counter::Counter;
70    ///
71    /// struct ManyCounters {
72    ///     counters: Vec<Counter>,
73    /// }
74    /// ```
75    ///
76    /// We can store the state of multiple counters now. However, the
77    /// __messages__ we implemented before describe the user interactions
78    /// of a __single__ counter. Right now, we need to also identify which
79    /// counter is receiving user interactions. Can we use composition again?
80    /// Yes.
81    ///
82    /// ```
83    /// # mod counter {
84    /// #     #[derive(Debug, Clone, Copy)]
85    /// #     pub enum Message {}
86    /// # }
87    /// #[derive(Debug, Clone, Copy)]
88    /// pub enum Message {
89    ///     Counter(usize, counter::Message)
90    /// }
91    /// ```
92    ///
93    /// We compose the previous __messages__ with the index of the counter
94    /// producing them. Let's implement our __view logic__ now:
95    ///
96    /// ```no_run
97    /// # mod iced {
98    /// #     pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, ()>;
99    /// #
100    /// #     pub mod widget {
101    /// #         pub fn row<'a, Message>(iter: impl IntoIterator<Item = super::Element<'a, Message>>) -> super::Element<'a, Message> {
102    /// #             unimplemented!()
103    /// #         }
104    /// #     }
105    /// # }
106    /// #
107    /// # mod counter {
108    /// #     #[derive(Debug, Clone, Copy)]
109    /// #     pub enum Message {}
110    /// #     pub struct Counter;
111    /// #
112    /// #     pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, ()>;
113    /// #
114    /// #     impl Counter {
115    /// #         pub fn view(&self) -> Element<Message> {
116    /// #             unimplemented!()
117    /// #         }
118    /// #     }
119    /// # }
120    /// #
121    /// use counter::Counter;
122    ///
123    /// use iced::widget::row;
124    /// use iced::Element;
125    ///
126    /// struct ManyCounters {
127    ///     counters: Vec<Counter>,
128    /// }
129    ///
130    /// #[derive(Debug, Clone, Copy)]
131    /// pub enum Message {
132    ///     Counter(usize, counter::Message),
133    /// }
134    ///
135    /// impl ManyCounters {
136    ///     pub fn view(&self) -> Element<Message> {
137    ///         // We can quickly populate a `row` by mapping our counters
138    ///         row(
139    ///             self.counters
140    ///                 .iter()
141    ///                 .map(Counter::view)
142    ///                 .enumerate()
143    ///                 .map(|(index, counter)| {
144    ///                     // Here we turn our `Element<counter::Message>` into
145    ///                     // an `Element<Message>` by combining the `index` and the
146    ///                     // message of the `element`.
147    ///                     counter.map(move |message| Message::Counter(index, message))
148    ///                 }),
149    ///         )
150    ///         .into()
151    ///     }
152    /// }
153    /// ```
154    ///
155    /// Finally, our __update logic__ is pretty straightforward: simple
156    /// delegation.
157    ///
158    /// ```
159    /// # mod counter {
160    /// #     #[derive(Debug, Clone, Copy)]
161    /// #     pub enum Message {}
162    /// #     pub struct Counter;
163    /// #
164    /// #     impl Counter {
165    /// #         pub fn update(&mut self, _message: Message) {}
166    /// #     }
167    /// # }
168    /// #
169    /// # use counter::Counter;
170    /// #
171    /// # struct ManyCounters {
172    /// #     counters: Vec<Counter>,
173    /// # }
174    /// #
175    /// # #[derive(Debug, Clone, Copy)]
176    /// # pub enum Message {
177    /// #    Counter(usize, counter::Message)
178    /// # }
179    /// impl ManyCounters {
180    ///     pub fn update(&mut self, message: Message) {
181    ///         match message {
182    ///             Message::Counter(index, counter_msg) => {
183    ///                 if let Some(counter) = self.counters.get_mut(index) {
184    ///                     counter.update(counter_msg);
185    ///                 }
186    ///             }
187    ///         }
188    ///     }
189    /// }
190    /// ```
191    pub fn map<B>(
192        self,
193        f: impl Fn(Message) -> B + 'a,
194    ) -> Element<'a, B, Theme, Renderer>
195    where
196        Message: 'a,
197        Theme: 'a,
198        Renderer: crate::Renderer + 'a,
199        B: 'a,
200    {
201        Element::new(Map::new(self.widget, f))
202    }
203
204    /// Marks the [`Element`] as _to-be-explained_.
205    ///
206    /// The [`Renderer`] will explain the layout of the [`Element`] graphically.
207    /// This can be very useful for debugging your layout!
208    ///
209    /// [`Renderer`]: crate::Renderer
210    pub fn explain<C: Into<Color>>(
211        self,
212        color: C,
213    ) -> Element<'a, Message, Theme, Renderer>
214    where
215        Message: 'a,
216        Theme: 'a,
217        Renderer: crate::Renderer + 'a,
218    {
219        Element {
220            widget: Box::new(Explain::new(self, color.into())),
221        }
222    }
223}
224
225impl<'a, Message, Theme, Renderer>
226    Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
227    for Element<'a, Message, Theme, Renderer>
228{
229    fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
230        self.widget.borrow()
231    }
232}
233
234impl<'a, Message, Theme, Renderer>
235    Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
236    for &Element<'a, Message, Theme, Renderer>
237{
238    fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
239        self.widget.borrow()
240    }
241}
242
243impl<'a, Message, Theme, Renderer>
244    Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
245    for &mut Element<'a, Message, Theme, Renderer>
246{
247    fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
248        self.widget.borrow()
249    }
250}
251
252impl<'a, Message, Theme, Renderer>
253    BorrowMut<dyn Widget<Message, Theme, Renderer> + 'a>
254    for &mut Element<'a, Message, Theme, Renderer>
255{
256    fn borrow_mut(
257        &mut self,
258    ) -> &mut (dyn Widget<Message, Theme, Renderer> + 'a) {
259        self.widget.borrow_mut()
260    }
261}
262
263impl<'a, Message, Theme, Renderer>
264    BorrowMut<dyn Widget<Message, Theme, Renderer> + 'a>
265    for Element<'a, Message, Theme, Renderer>
266{
267    fn borrow_mut(
268        &mut self,
269    ) -> &mut (dyn Widget<Message, Theme, Renderer> + 'a) {
270        self.widget.borrow_mut()
271    }
272}
273
274struct Map<'a, A, B, Theme, Renderer> {
275    widget: Box<dyn Widget<A, Theme, Renderer> + 'a>,
276    mapper: Box<dyn Fn(A) -> B + 'a>,
277}
278
279impl<'a, A, B, Theme, Renderer> Map<'a, A, B, Theme, Renderer> {
280    pub fn new<F>(
281        widget: Box<dyn Widget<A, Theme, Renderer> + 'a>,
282        mapper: F,
283    ) -> Map<'a, A, B, Theme, Renderer>
284    where
285        F: 'a + Fn(A) -> B,
286    {
287        Map {
288            widget,
289            mapper: Box::new(mapper),
290        }
291    }
292}
293
294impl<'a, A, B, Theme, Renderer> Widget<B, Theme, Renderer>
295    for Map<'a, A, B, Theme, Renderer>
296where
297    Renderer: crate::Renderer + 'a,
298    A: 'a,
299    B: 'a,
300{
301    fn tag(&self) -> tree::Tag {
302        self.widget.tag()
303    }
304
305    fn state(&self) -> tree::State {
306        self.widget.state()
307    }
308
309    fn children(&self) -> Vec<Tree> {
310        self.widget.children()
311    }
312
313    fn diff(&mut self, tree: &mut Tree) {
314        self.widget.diff(tree);
315    }
316
317    fn size(&self) -> Size<Length> {
318        self.widget.size()
319    }
320
321    fn size_hint(&self) -> Size<Length> {
322        self.widget.size_hint()
323    }
324
325    fn layout(
326        &self,
327        tree: &mut Tree,
328        renderer: &Renderer,
329        limits: &layout::Limits,
330    ) -> layout::Node {
331        self.widget.layout(tree, renderer, limits)
332    }
333
334    fn operate(
335        &self,
336        tree: &mut Tree,
337        layout: Layout<'_>,
338        renderer: &Renderer,
339        operation: &mut dyn widget::Operation,
340    ) {
341        self.widget.operate(tree, layout, renderer, operation);
342    }
343
344    fn on_event(
345        &mut self,
346        tree: &mut Tree,
347        event: Event,
348        layout: Layout<'_>,
349        cursor: mouse::Cursor,
350        renderer: &Renderer,
351        clipboard: &mut dyn Clipboard,
352        shell: &mut Shell<'_, B>,
353        viewport: &Rectangle,
354    ) -> event::Status {
355        let mut local_messages = Vec::new();
356        let mut local_shell = Shell::new(&mut local_messages);
357
358        let status = self.widget.on_event(
359            tree,
360            event,
361            layout,
362            cursor,
363            renderer,
364            clipboard,
365            &mut local_shell,
366            viewport,
367        );
368
369        shell.merge(local_shell, &self.mapper);
370
371        status
372    }
373
374    fn draw(
375        &self,
376        tree: &Tree,
377        renderer: &mut Renderer,
378        theme: &Theme,
379        style: &renderer::Style,
380        layout: Layout<'_>,
381        cursor: mouse::Cursor,
382        viewport: &Rectangle,
383    ) {
384        self.widget
385            .draw(tree, renderer, theme, style, layout, cursor, viewport);
386    }
387
388    fn mouse_interaction(
389        &self,
390        tree: &Tree,
391        layout: Layout<'_>,
392        cursor: mouse::Cursor,
393        viewport: &Rectangle,
394        renderer: &Renderer,
395    ) -> mouse::Interaction {
396        self.widget
397            .mouse_interaction(tree, layout, cursor, viewport, renderer)
398    }
399
400    fn overlay<'b>(
401        &'b mut self,
402        tree: &'b mut Tree,
403        layout: Layout<'_>,
404        renderer: &Renderer,
405        translation: Vector,
406    ) -> Option<overlay::Element<'b, B, Theme, Renderer>> {
407        let mapper = &self.mapper;
408
409        self.widget
410            .overlay(tree, layout, renderer, translation)
411            .map(move |overlay| overlay.map(mapper))
412    }
413
414    #[cfg(feature = "a11y")]
415    fn a11y_nodes(
416        &self,
417        _layout: Layout<'_>,
418        _state: &Tree,
419        _cursor_position: mouse::Cursor,
420    ) -> iced_accessibility::A11yTree {
421        self.widget.a11y_nodes(_layout, _state, _cursor_position)
422    }
423
424    fn id(&self) -> Option<Id> {
425        self.widget.id()
426    }
427
428    fn set_id(&mut self, id: Id) {
429        self.widget.set_id(id);
430    }
431
432    fn drag_destinations(
433        &self,
434        state: &Tree,
435        layout: Layout<'_>,
436        renderer: &Renderer,
437        dnd_rectangles: &mut crate::clipboard::DndDestinationRectangles,
438    ) {
439        self.widget
440            .drag_destinations(state, layout, renderer, dnd_rectangles);
441    }
442}
443
444struct Explain<'a, Message, Theme, Renderer: crate::Renderer> {
445    element: Element<'a, Message, Theme, Renderer>,
446    color: Color,
447}
448
449impl<'a, Message, Theme, Renderer> Explain<'a, Message, Theme, Renderer>
450where
451    Renderer: crate::Renderer,
452{
453    fn new(
454        element: Element<'a, Message, Theme, Renderer>,
455        color: Color,
456    ) -> Self {
457        Explain { element, color }
458    }
459}
460
461impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
462    for Explain<'a, Message, Theme, Renderer>
463where
464    Renderer: crate::Renderer,
465{
466    fn size(&self) -> Size<Length> {
467        self.element.widget.size()
468    }
469
470    fn size_hint(&self) -> Size<Length> {
471        self.element.widget.size_hint()
472    }
473
474    fn tag(&self) -> tree::Tag {
475        self.element.widget.tag()
476    }
477
478    fn state(&self) -> tree::State {
479        self.element.widget.state()
480    }
481
482    fn children(&self) -> Vec<Tree> {
483        self.element.widget.children()
484    }
485
486    fn diff(&mut self, tree: &mut Tree) {
487        self.element.widget.diff(tree);
488    }
489
490    fn layout(
491        &self,
492        tree: &mut Tree,
493        renderer: &Renderer,
494        limits: &layout::Limits,
495    ) -> layout::Node {
496        self.element.widget.layout(tree, renderer, limits)
497    }
498
499    fn operate(
500        &self,
501        state: &mut Tree,
502        layout: Layout<'_>,
503        renderer: &Renderer,
504        operation: &mut dyn widget::Operation,
505    ) {
506        self.element
507            .widget
508            .operate(state, layout, renderer, operation);
509    }
510
511    fn on_event(
512        &mut self,
513        state: &mut Tree,
514        event: Event,
515        layout: Layout<'_>,
516        cursor: mouse::Cursor,
517        renderer: &Renderer,
518        clipboard: &mut dyn Clipboard,
519        shell: &mut Shell<'_, Message>,
520        viewport: &Rectangle,
521    ) -> event::Status {
522        self.element.widget.on_event(
523            state, event, layout, cursor, renderer, clipboard, shell, viewport,
524        )
525    }
526
527    fn draw(
528        &self,
529        state: &Tree,
530        renderer: &mut Renderer,
531        theme: &Theme,
532        style: &renderer::Style,
533        layout: Layout<'_>,
534        cursor: mouse::Cursor,
535        viewport: &Rectangle,
536    ) {
537        fn explain_layout<Renderer: crate::Renderer>(
538            renderer: &mut Renderer,
539            color: Color,
540            layout: Layout<'_>,
541        ) {
542            renderer.fill_quad(
543                renderer::Quad {
544                    bounds: layout.bounds(),
545                    border: Border {
546                        color,
547                        width: 1.0,
548                        ..Border::default()
549                    },
550                    ..renderer::Quad::default()
551                },
552                Color::TRANSPARENT,
553            );
554
555            for child in layout.children() {
556                explain_layout(renderer, color, child);
557            }
558        }
559
560        self.element
561            .widget
562            .draw(state, renderer, theme, style, layout, cursor, viewport);
563
564        explain_layout(renderer, self.color, layout);
565    }
566
567    fn mouse_interaction(
568        &self,
569        state: &Tree,
570        layout: Layout<'_>,
571        cursor: mouse::Cursor,
572        viewport: &Rectangle,
573        renderer: &Renderer,
574    ) -> mouse::Interaction {
575        self.element
576            .widget
577            .mouse_interaction(state, layout, cursor, viewport, renderer)
578    }
579
580    fn overlay<'b>(
581        &'b mut self,
582        state: &'b mut Tree,
583        layout: Layout<'_>,
584        renderer: &Renderer,
585        translation: Vector,
586    ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
587        self.element
588            .widget
589            .overlay(state, layout, renderer, translation)
590    }
591
592    fn id(&self) -> Option<Id> {
593        self.element.widget.id()
594    }
595
596    fn set_id(&mut self, id: Id) {
597        self.element.widget.set_id(id);
598    }
599
600    fn drag_destinations(
601        &self,
602        state: &Tree,
603        layout: Layout<'_>,
604        renderer: &Renderer,
605        dnd_rectangles: &mut crate::clipboard::DndDestinationRectangles,
606    ) {
607        self.element.widget.drag_destinations(
608            state,
609            layout,
610            renderer,
611            dnd_rectangles,
612        );
613    }
614    // TODO maybe a11y_nodes
615}