Skip to main content

iced_core/
element.rs

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