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
12pub 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 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 pub fn as_widget(&self) -> &dyn Widget<Message, Theme, Renderer> {
38 self.widget.as_ref()
39 }
40
41 pub fn as_widget_mut(&mut self) -> &mut dyn Widget<Message, Theme, Renderer> {
43 self.widget.as_mut()
44 }
45
46 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 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 renderer: &Renderer,
309 operation: &mut dyn widget::Operation,
310 ) {
311 self.widget.operate(tree, layout, renderer, operation);
312 }
313
314 fn update(
315 &mut self,
316 tree: &mut Tree,
317 event: &Event,
318 layout: Layout<'_>,
319 cursor: mouse::Cursor,
320 renderer: &Renderer,
321 shell: &mut Shell<'_, B>,
322 viewport: &Rectangle,
323 ) {
324 let mut local_messages = shell::Bus::new();
325 let mut local_shell = shell.local(&mut local_messages);
326
327 self.widget.update(
328 tree,
329 event,
330 layout,
331 cursor,
332 renderer,
333 &mut local_shell,
334 viewport,
335 );
336
337 shell.merge(local_shell, &self.mapper);
338 }
339
340 fn draw(
341 &self,
342 tree: &Tree,
343 renderer: &mut Renderer,
344 theme: &Theme,
345 style: &renderer::Style,
346 layout: Layout<'_>,
347 cursor: mouse::Cursor,
348 viewport: &Rectangle,
349 ) {
350 self.widget
351 .draw(tree, renderer, theme, style, layout, cursor, viewport);
352 }
353
354 fn mouse_interaction(
355 &self,
356 tree: &Tree,
357 layout: Layout<'_>,
358 cursor: mouse::Cursor,
359 viewport: &Rectangle,
360 renderer: &Renderer,
361 ) -> mouse::Interaction {
362 self.widget
363 .mouse_interaction(tree, layout, cursor, viewport, renderer)
364 }
365
366 fn overlay<'b>(
367 &'b mut self,
368 tree: &'b mut Tree,
369 layout: Layout<'b>,
370 renderer: &Renderer,
371 viewport: &Rectangle,
372 translation: Vector,
373 ) -> Option<overlay::Element<'b, B, Theme, Renderer>> {
374 let mapper = &self.mapper;
375
376 self.widget
377 .overlay(tree, layout, renderer, viewport, translation)
378 .map(move |overlay| overlay.map(mapper))
379 }
380}
381
382struct Explain<'a, Message, Theme, Renderer: crate::Renderer> {
383 element: Element<'a, Message, Theme, Renderer>,
384 color: Color,
385}
386
387impl<'a, Message, Theme, Renderer> Explain<'a, Message, Theme, Renderer>
388where
389 Renderer: crate::Renderer,
390{
391 fn new(element: Element<'a, Message, Theme, Renderer>, color: Color) -> Self {
392 Explain { element, color }
393 }
394}
395
396impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
397 for Explain<'_, Message, Theme, Renderer>
398where
399 Renderer: crate::Renderer,
400{
401 fn size(&self) -> Size<Length> {
402 self.element.widget.size()
403 }
404
405 fn tag(&self) -> tree::Tag {
406 self.element.widget.tag()
407 }
408
409 fn state(&self) -> tree::State {
410 self.element.widget.state()
411 }
412
413 fn diff(&mut self, tree: &mut Tree) {
414 self.element.widget.diff(tree);
415 }
416
417 fn layout(
418 &mut self,
419 tree: &mut Tree,
420 renderer: &Renderer,
421 limits: &layout::Limits,
422 ) -> layout::Node {
423 self.element.widget.layout(tree, renderer, limits)
424 }
425
426 fn operate(
427 &mut self,
428 tree: &mut Tree,
429 layout: Layout<'_>,
430 renderer: &Renderer,
431 operation: &mut dyn widget::Operation,
432 ) {
433 self.element
434 .widget
435 .operate(tree, layout, renderer, operation);
436 }
437
438 fn update(
439 &mut self,
440 tree: &mut Tree,
441 event: &Event,
442 layout: Layout<'_>,
443 cursor: mouse::Cursor,
444 renderer: &Renderer,
445 shell: &mut Shell<'_, Message>,
446 viewport: &Rectangle,
447 ) {
448 self.element
449 .widget
450 .update(tree, event, layout, cursor, renderer, shell, viewport);
451 }
452
453 fn draw(
454 &self,
455 tree: &Tree,
456 renderer: &mut Renderer,
457 theme: &Theme,
458 style: &renderer::Style,
459 layout: Layout<'_>,
460 cursor: mouse::Cursor,
461 viewport: &Rectangle,
462 ) {
463 fn explain_layout<Renderer: crate::Renderer>(
464 renderer: &mut Renderer,
465 color: Color,
466 layout: Layout<'_>,
467 ) {
468 renderer.fill_quad(
469 renderer::Quad {
470 bounds: layout.bounds(),
471 border: Border {
472 color,
473 width: 1.0,
474 ..Border::default()
475 },
476 ..renderer::Quad::default()
477 },
478 Color::TRANSPARENT,
479 );
480
481 for child in layout.children() {
482 explain_layout(renderer, color, child);
483 }
484 }
485
486 self.element
487 .widget
488 .draw(tree, renderer, theme, style, layout, cursor, viewport);
489
490 renderer.with_layer(Rectangle::INFINITE, |renderer| {
491 explain_layout(renderer, self.color, layout);
492 });
493 }
494
495 fn mouse_interaction(
496 &self,
497 tree: &Tree,
498 layout: Layout<'_>,
499 cursor: mouse::Cursor,
500 viewport: &Rectangle,
501 renderer: &Renderer,
502 ) -> mouse::Interaction {
503 self.element
504 .widget
505 .mouse_interaction(tree, layout, cursor, viewport, renderer)
506 }
507
508 fn overlay<'b>(
509 &'b mut self,
510 tree: &'b mut Tree,
511 layout: Layout<'b>,
512 renderer: &Renderer,
513 viewport: &Rectangle,
514 translation: Vector,
515 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
516 self.element
517 .widget
518 .overlay(tree, layout, renderer, viewport, translation)
519 }
520}
521
522impl<'a, T, Message, Theme, Renderer> From<Option<T>> for Element<'a, Message, Theme, Renderer>
523where
524 T: Into<Self>,
525 Renderer: crate::Renderer,
526{
527 fn from(value: Option<T>) -> Self {
528 value
529 .map(T::into)
530 .unwrap_or_else(|| Element::new(widget::Void))
531 }
532}
533
534impl<'a, Message, Theme, Renderer> From<widget::Void> for Element<'a, Message, Theme, Renderer>
535where
536 Renderer: crate::Renderer,
537{
538 fn from(void: widget::Void) -> Self {
539 Element::new(void)
540 }
541}