use crate::core::event; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; use crate::core::renderer; use crate::core::widget; use crate::core::{ Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size, }; use std::cell::RefCell; /// An [`Overlay`] container that displays nested overlays #[allow(missing_debug_implementations)] pub struct Nested<'a, Message, Renderer> { overlay: Inner<'a, Message, Renderer>, } impl<'a, Message, Renderer> Nested<'a, Message, Renderer> { /// Creates a nested overlay from the provided [`overlay::Element`] pub fn new(element: overlay::Element<'a, Message, Renderer>) -> Self { Self { overlay: Inner(RefCell::new(element)), } } } struct Inner<'a, Message, Renderer>( RefCell>, ); impl<'a, Message, Renderer> Inner<'a, Message, Renderer> { fn with_element_mut( &self, mut f: impl FnMut(&mut overlay::Element<'_, Message, Renderer>) -> T, ) -> T { (f)(&mut self.0.borrow_mut()) } } impl<'a, Message, Renderer> Overlay for Nested<'a, Message, Renderer> where Renderer: renderer::Renderer, { fn layout( &self, renderer: &Renderer, bounds: Size, position: Point, ) -> layout::Node { fn recurse( element: &mut overlay::Element<'_, Message, Renderer>, renderer: &Renderer, bounds: Size, position: Point, ) -> Vec where Renderer: renderer::Renderer, { let translation = position - Point::ORIGIN; let node = element.layout(renderer, bounds, translation); if let Some(mut overlay) = element.overlay(Layout::new(&node), renderer) { vec![node] .into_iter() .chain(recurse(&mut overlay, renderer, bounds, position)) .collect() } else { vec![node] } } self.overlay.with_element_mut(|element| { layout::Node::with_children( bounds, recurse(element, renderer, bounds, position), ) }) } fn draw( &self, renderer: &mut Renderer, theme: &::Theme, style: &renderer::Style, layout: Layout<'_>, cursor: mouse::Cursor, ) { fn recurse<'a, Message, Renderer>( element: &mut overlay::Element<'_, Message, Renderer>, mut layouts: impl Iterator>, renderer: &mut Renderer, theme: &::Theme, style: &renderer::Style, cursor: mouse::Cursor, ) where Renderer: renderer::Renderer, { let layout = layouts.next().unwrap(); element.draw(renderer, theme, style, layout, cursor); if let Some(mut overlay) = element.overlay(layout, renderer) { recurse(&mut overlay, layouts, renderer, theme, style, cursor); } } self.overlay.with_element_mut(|element| { let layouts = layout.children(); recurse(element, layouts, renderer, theme, style, cursor); }) } fn operate( &mut self, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) { fn recurse<'a, Message, Renderer>( element: &mut overlay::Element<'_, Message, Renderer>, mut layouts: impl Iterator>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) where Renderer: renderer::Renderer, { let layout = layouts.next().unwrap(); element.operate(layout, renderer, operation); if let Some(mut overlay) = element.overlay(layout, renderer) { recurse(&mut overlay, layouts, renderer, operation); } } let layouts = layout.children(); recurse(self.overlay.0.get_mut(), layouts, renderer, operation) } fn on_event( &mut self, event: Event, layout: Layout<'_>, cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { fn recurse<'a, Message, Renderer>( element: &mut overlay::Element<'_, Message, Renderer>, mut layouts: impl Iterator>, event: Event, cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status where Renderer: renderer::Renderer, { let layout = layouts.next().unwrap(); let status = if let Some(mut overlay) = element.overlay(layout, renderer) { recurse( &mut overlay, layouts, event.clone(), cursor, renderer, clipboard, shell, ) } else { event::Status::Ignored }; if matches!(status, event::Status::Ignored) { element .on_event(event, layout, cursor, renderer, clipboard, shell) } else { status } } let layouts = layout.children(); recurse( self.overlay.0.get_mut(), layouts, event, cursor, renderer, clipboard, shell, ) } fn mouse_interaction( &self, layout: Layout<'_>, cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { fn recurse<'a, Message, Renderer>( element: &mut overlay::Element<'_, Message, Renderer>, mut layouts: impl Iterator>, cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction where Renderer: renderer::Renderer, { let layout = layouts.next().unwrap(); let interaction = if let Some(mut overlay) = element.overlay(layout, renderer) { recurse(&mut overlay, layouts, cursor, viewport, renderer) } else { mouse::Interaction::default() }; element .mouse_interaction(layout, cursor, viewport, renderer) .max(interaction) } self.overlay.with_element_mut(|element| { let layouts = layout.children(); recurse(element, layouts, cursor, viewport, renderer) }) } fn is_over( &self, layout: Layout<'_>, renderer: &Renderer, cursor_position: Point, ) -> bool { fn recurse<'a, Message, Renderer>( element: &mut overlay::Element<'_, Message, Renderer>, mut layouts: impl Iterator>, renderer: &Renderer, cursor_position: Point, ) -> bool where Renderer: renderer::Renderer, { let layout = layouts.next().unwrap(); let is_over = element.is_over(layout, renderer, cursor_position); if is_over { return true; } if let Some(mut overlay) = element.overlay(layout, renderer) { recurse(&mut overlay, layouts, renderer, cursor_position) } else { false } } self.overlay.with_element_mut(|element| { let layouts = layout.children(); recurse(element, layouts, renderer, cursor_position) }) } fn overlay<'b>( &'b mut self, _layout: Layout<'_>, _renderer: &Renderer, ) -> Option> { None } }