iced_core/overlay/
element.rs

1pub use crate::Overlay;
2
3use crate::event::{self, Event};
4use crate::layout;
5use crate::mouse;
6use crate::renderer;
7use crate::widget;
8use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size};
9
10/// A generic [`Overlay`].
11#[allow(missing_debug_implementations)]
12pub struct Element<'a, Message, Theme, Renderer> {
13    overlay: Box<dyn Overlay<Message, Theme, Renderer> + 'a>,
14}
15
16impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer>
17where
18    Renderer: crate::Renderer,
19{
20    /// Creates a new [`Element`] containing the given [`Overlay`].
21    pub fn new(
22        overlay: Box<dyn Overlay<Message, Theme, Renderer> + 'a>,
23    ) -> Self {
24        Self { overlay }
25    }
26
27    /// Applies a transformation to the produced message of the [`Element`].
28    pub fn map<B>(
29        self,
30        f: &'a dyn Fn(Message) -> B,
31    ) -> Element<'a, B, Theme, Renderer>
32    where
33        Message: 'a,
34        Theme: 'a,
35        Renderer: 'a,
36        B: 'a,
37    {
38        Element {
39            overlay: Box::new(Map::new(self.overlay, f)),
40        }
41    }
42
43    /// Computes the layout of the [`Element`] in the given bounds.
44    pub fn layout(
45        &mut self,
46        renderer: &Renderer,
47        bounds: Size,
48    ) -> layout::Node {
49        self.overlay.layout(renderer, bounds)
50    }
51
52    /// Processes a runtime [`Event`].
53    pub fn on_event(
54        &mut self,
55        event: Event,
56        layout: Layout<'_>,
57        cursor: mouse::Cursor,
58        renderer: &Renderer,
59        clipboard: &mut dyn Clipboard,
60        shell: &mut Shell<'_, Message>,
61    ) -> event::Status {
62        self.overlay
63            .on_event(event, layout, cursor, renderer, clipboard, shell)
64    }
65
66    /// Returns the current [`mouse::Interaction`] of the [`Element`].
67    pub fn mouse_interaction(
68        &self,
69        layout: Layout<'_>,
70        cursor: mouse::Cursor,
71        viewport: &Rectangle,
72        renderer: &Renderer,
73    ) -> mouse::Interaction {
74        self.overlay
75            .mouse_interaction(layout, cursor, viewport, renderer)
76    }
77
78    /// Draws the [`Element`] and its children using the given [`Layout`].
79    pub fn draw(
80        &self,
81        renderer: &mut Renderer,
82        theme: &Theme,
83        style: &renderer::Style,
84        layout: Layout<'_>,
85        cursor: mouse::Cursor,
86    ) {
87        self.overlay.draw(renderer, theme, style, layout, cursor);
88    }
89
90    /// Applies a [`widget::Operation`] to the [`Element`].
91    pub fn operate(
92        &mut self,
93        layout: Layout<'_>,
94        renderer: &Renderer,
95        operation: &mut dyn widget::Operation,
96    ) {
97        self.overlay.operate(layout, renderer, operation);
98    }
99
100    /// Returns true if the cursor is over the [`Element`].
101    pub fn is_over(
102        &self,
103        layout: Layout<'_>,
104        renderer: &Renderer,
105        cursor_position: Point,
106    ) -> bool {
107        self.overlay.is_over(layout, renderer, cursor_position)
108    }
109
110    /// Returns the nested overlay of the [`Element`], if there is any.
111    pub fn overlay<'b>(
112        &'b mut self,
113        layout: Layout<'_>,
114        renderer: &Renderer,
115    ) -> Option<Element<'b, Message, Theme, Renderer>> {
116        self.overlay.overlay(layout, renderer)
117    }
118}
119
120struct Map<'a, A, B, Theme, Renderer> {
121    content: Box<dyn Overlay<A, Theme, Renderer> + 'a>,
122    mapper: &'a dyn Fn(A) -> B,
123}
124
125impl<'a, A, B, Theme, Renderer> Map<'a, A, B, Theme, Renderer> {
126    pub fn new(
127        content: Box<dyn Overlay<A, Theme, Renderer> + 'a>,
128        mapper: &'a dyn Fn(A) -> B,
129    ) -> Map<'a, A, B, Theme, Renderer> {
130        Map { content, mapper }
131    }
132}
133
134impl<'a, A, B, Theme, Renderer> Overlay<B, Theme, Renderer>
135    for Map<'a, A, B, Theme, Renderer>
136where
137    Renderer: crate::Renderer,
138{
139    fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node {
140        self.content.layout(renderer, bounds)
141    }
142
143    fn operate(
144        &mut self,
145        layout: Layout<'_>,
146        renderer: &Renderer,
147        operation: &mut dyn widget::Operation,
148    ) {
149        self.content.operate(layout, renderer, operation);
150    }
151
152    fn on_event(
153        &mut self,
154        event: Event,
155        layout: Layout<'_>,
156        cursor: mouse::Cursor,
157        renderer: &Renderer,
158        clipboard: &mut dyn Clipboard,
159        shell: &mut Shell<'_, B>,
160    ) -> event::Status {
161        let mut local_messages = Vec::new();
162        let mut local_shell = Shell::new(&mut local_messages);
163
164        let event_status = self.content.on_event(
165            event,
166            layout,
167            cursor,
168            renderer,
169            clipboard,
170            &mut local_shell,
171        );
172
173        shell.merge(local_shell, self.mapper);
174
175        event_status
176    }
177
178    fn mouse_interaction(
179        &self,
180        layout: Layout<'_>,
181        cursor: mouse::Cursor,
182        viewport: &Rectangle,
183        renderer: &Renderer,
184    ) -> mouse::Interaction {
185        self.content
186            .mouse_interaction(layout, cursor, viewport, renderer)
187    }
188
189    fn draw(
190        &self,
191        renderer: &mut Renderer,
192        theme: &Theme,
193        style: &renderer::Style,
194        layout: Layout<'_>,
195        cursor: mouse::Cursor,
196    ) {
197        self.content.draw(renderer, theme, style, layout, cursor);
198    }
199
200    fn is_over(
201        &self,
202        layout: Layout<'_>,
203        renderer: &Renderer,
204        cursor_position: Point,
205    ) -> bool {
206        self.content.is_over(layout, renderer, cursor_position)
207    }
208
209    fn overlay<'b>(
210        &'b mut self,
211        layout: Layout<'_>,
212        renderer: &Renderer,
213    ) -> Option<Element<'b, B, Theme, Renderer>> {
214        self.content
215            .overlay(layout, renderer)
216            .map(|overlay| overlay.map(self.mapper))
217    }
218}