1use crate::layout;
2use crate::mouse;
3use crate::overlay;
4use crate::renderer;
5use crate::widget;
6use crate::widget::tree::{self, Tree};
7use crate::{
8 Border, Clipboard, Color, Event, Layout, Length, Rectangle, Shell, Size,
9 Vector, Widget,
10};
11
12use std::borrow::Borrow;
13
14#[allow(missing_debug_implementations)]
24pub struct Element<'a, Message, Theme, Renderer> {
25 widget: Box<dyn Widget<Message, Theme, Renderer> + 'a>,
26}
27
28impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
29 pub fn new(widget: impl Widget<Message, Theme, Renderer> + 'a) -> Self
31 where
32 Renderer: crate::Renderer,
33 {
34 Self {
35 widget: Box::new(widget),
36 }
37 }
38
39 pub fn as_widget(&self) -> &dyn Widget<Message, Theme, Renderer> {
41 self.widget.as_ref()
42 }
43
44 pub fn as_widget_mut(
46 &mut self,
47 ) -> &mut dyn Widget<Message, Theme, Renderer> {
48 self.widget.as_mut()
49 }
50
51 pub fn map<B>(
191 self,
192 f: impl Fn(Message) -> B + 'a,
193 ) -> Element<'a, B, Theme, Renderer>
194 where
195 Message: 'a,
196 Theme: 'a,
197 Renderer: crate::Renderer + 'a,
198 B: 'a,
199 {
200 Element::new(Map::new(self.widget, f))
201 }
202
203 pub fn explain<C: Into<Color>>(
210 self,
211 color: C,
212 ) -> Element<'a, Message, Theme, Renderer>
213 where
214 Message: 'a,
215 Theme: 'a,
216 Renderer: crate::Renderer + 'a,
217 {
218 Element {
219 widget: Box::new(Explain::new(self, color.into())),
220 }
221 }
222}
223
224impl<'a, Message, Theme, Renderer>
225 Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
226 for Element<'a, Message, Theme, Renderer>
227{
228 fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
229 self.widget.borrow()
230 }
231}
232
233impl<'a, Message, Theme, Renderer>
234 Borrow<dyn Widget<Message, Theme, Renderer> + 'a>
235 for &Element<'a, Message, Theme, Renderer>
236{
237 fn borrow(&self) -> &(dyn Widget<Message, Theme, Renderer> + 'a) {
238 self.widget.borrow()
239 }
240}
241
242struct Map<'a, A, B, Theme, Renderer> {
243 widget: Box<dyn Widget<A, Theme, Renderer> + 'a>,
244 mapper: Box<dyn Fn(A) -> B + 'a>,
245}
246
247impl<'a, A, B, Theme, Renderer> Map<'a, A, B, Theme, Renderer> {
248 pub fn new<F>(
249 widget: Box<dyn Widget<A, Theme, Renderer> + 'a>,
250 mapper: F,
251 ) -> Map<'a, A, B, Theme, Renderer>
252 where
253 F: 'a + Fn(A) -> B,
254 {
255 Map {
256 widget,
257 mapper: Box::new(mapper),
258 }
259 }
260}
261
262impl<'a, A, B, Theme, Renderer> Widget<B, Theme, Renderer>
263 for Map<'a, A, B, Theme, Renderer>
264where
265 Renderer: crate::Renderer + 'a,
266 A: 'a,
267 B: 'a,
268{
269 fn tag(&self) -> tree::Tag {
270 self.widget.tag()
271 }
272
273 fn state(&self) -> tree::State {
274 self.widget.state()
275 }
276
277 fn children(&self) -> Vec<Tree> {
278 self.widget.children()
279 }
280
281 fn diff(&self, tree: &mut Tree) {
282 self.widget.diff(tree);
283 }
284
285 fn size(&self) -> Size<Length> {
286 self.widget.size()
287 }
288
289 fn size_hint(&self) -> Size<Length> {
290 self.widget.size_hint()
291 }
292
293 fn layout(
294 &self,
295 tree: &mut Tree,
296 renderer: &Renderer,
297 limits: &layout::Limits,
298 ) -> layout::Node {
299 self.widget.layout(tree, renderer, limits)
300 }
301
302 fn operate(
303 &self,
304 tree: &mut Tree,
305 layout: Layout<'_>,
306 renderer: &Renderer,
307 operation: &mut dyn widget::Operation,
308 ) {
309 self.widget.operate(tree, layout, renderer, operation);
310 }
311
312 fn update(
313 &mut self,
314 tree: &mut Tree,
315 event: &Event,
316 layout: Layout<'_>,
317 cursor: mouse::Cursor,
318 renderer: &Renderer,
319 clipboard: &mut dyn Clipboard,
320 shell: &mut Shell<'_, B>,
321 viewport: &Rectangle,
322 ) {
323 let mut local_messages = Vec::new();
324 let mut local_shell = Shell::new(&mut local_messages);
325
326 self.widget.update(
327 tree,
328 event,
329 layout,
330 cursor,
331 renderer,
332 clipboard,
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(
392 element: Element<'a, Message, Theme, Renderer>,
393 color: Color,
394 ) -> Self {
395 Explain { element, color }
396 }
397}
398
399impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
400 for Explain<'_, Message, Theme, Renderer>
401where
402 Renderer: crate::Renderer,
403{
404 fn size(&self) -> Size<Length> {
405 self.element.widget.size()
406 }
407
408 fn size_hint(&self) -> Size<Length> {
409 self.element.widget.size_hint()
410 }
411
412 fn tag(&self) -> tree::Tag {
413 self.element.widget.tag()
414 }
415
416 fn state(&self) -> tree::State {
417 self.element.widget.state()
418 }
419
420 fn children(&self) -> Vec<Tree> {
421 self.element.widget.children()
422 }
423
424 fn diff(&self, tree: &mut Tree) {
425 self.element.widget.diff(tree);
426 }
427
428 fn layout(
429 &self,
430 tree: &mut Tree,
431 renderer: &Renderer,
432 limits: &layout::Limits,
433 ) -> layout::Node {
434 self.element.widget.layout(tree, renderer, limits)
435 }
436
437 fn operate(
438 &self,
439 state: &mut Tree,
440 layout: Layout<'_>,
441 renderer: &Renderer,
442 operation: &mut dyn widget::Operation,
443 ) {
444 self.element
445 .widget
446 .operate(state, layout, renderer, operation);
447 }
448
449 fn update(
450 &mut self,
451 state: &mut Tree,
452 event: &Event,
453 layout: Layout<'_>,
454 cursor: mouse::Cursor,
455 renderer: &Renderer,
456 clipboard: &mut dyn Clipboard,
457 shell: &mut Shell<'_, Message>,
458 viewport: &Rectangle,
459 ) {
460 self.element.widget.update(
461 state, event, layout, cursor, renderer, clipboard, shell, viewport,
462 );
463 }
464
465 fn draw(
466 &self,
467 state: &Tree,
468 renderer: &mut Renderer,
469 theme: &Theme,
470 style: &renderer::Style,
471 layout: Layout<'_>,
472 cursor: mouse::Cursor,
473 viewport: &Rectangle,
474 ) {
475 fn explain_layout<Renderer: crate::Renderer>(
476 renderer: &mut Renderer,
477 color: Color,
478 layout: Layout<'_>,
479 ) {
480 renderer.fill_quad(
481 renderer::Quad {
482 bounds: layout.bounds(),
483 border: Border {
484 color,
485 width: 1.0,
486 ..Border::default()
487 },
488 ..renderer::Quad::default()
489 },
490 Color::TRANSPARENT,
491 );
492
493 for child in layout.children() {
494 explain_layout(renderer, color, child);
495 }
496 }
497
498 self.element
499 .widget
500 .draw(state, renderer, theme, style, layout, cursor, viewport);
501
502 explain_layout(renderer, self.color, layout);
503 }
504
505 fn mouse_interaction(
506 &self,
507 state: &Tree,
508 layout: Layout<'_>,
509 cursor: mouse::Cursor,
510 viewport: &Rectangle,
511 renderer: &Renderer,
512 ) -> mouse::Interaction {
513 self.element
514 .widget
515 .mouse_interaction(state, layout, cursor, viewport, renderer)
516 }
517
518 fn overlay<'b>(
519 &'b mut self,
520 state: &'b mut Tree,
521 layout: Layout<'b>,
522 renderer: &Renderer,
523 viewport: &Rectangle,
524 translation: Vector,
525 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
526 self.element.widget.overlay(
527 state,
528 layout,
529 renderer,
530 viewport,
531 translation,
532 )
533 }
534}