iced_core/overlay/
element.rs

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