use iced::advanced::layout::{Limits, Node}; use iced::advanced::renderer::Style; use iced::advanced::widget::{Operation, Tree}; use iced::advanced::{Layout, Shell, Widget, mouse, overlay, text}; use iced::mouse::Cursor; use iced::widget::text_input::Catalog; use iced::{Element, Event, Length, Rectangle, Size, Vector}; pub struct NavigationArea<'a, Message, Theme, Renderer> where Theme: Catalog, Renderer: text::Renderer, { content: Element<'a, Message, Theme, Renderer>, on_back_click: Option, on_forward_click: Option, } impl<'a, Message, Theme, Renderer> NavigationArea<'a, Message, Theme, Renderer> where Message: Clone, Theme: Catalog, Renderer: text::Renderer, { #[must_use] pub fn new(content: impl Into>) -> Self { Self { content: content.into(), on_back_click: None, on_forward_click: None, } } #[must_use] pub fn on_back_click(mut self, message: Message) -> Self { self.on_back_click = Some(message); self } #[must_use] pub fn on_forward_click(mut self, message: Message) -> Self { self.on_forward_click = Some(message); self } } impl<'a, Message, Theme, Renderer> From> for Element<'a, Message, Theme, Renderer> where Message: Clone + 'a, Theme: Catalog + 'a, Renderer: text::Renderer + 'a, { fn from(value: NavigationArea<'a, Message, Theme, Renderer>) -> Self { Element::new(value) } } pub fn navigation_area<'a, Message, Theme, Renderer>( content: impl Into>, ) -> NavigationArea<'a, Message, Theme, Renderer> where Message: Clone, Theme: Catalog, Renderer: text::Renderer, { NavigationArea::new(content) } impl Widget for NavigationArea<'_, Message, Theme, Renderer> where Message: Clone, Theme: Catalog, Renderer: text::Renderer, { fn size(&self) -> Size { self.content.as_widget().size() } fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { self.content .as_widget_mut() .layout(&mut tree.children[0], renderer, limits) } fn draw( &self, tree: &Tree, renderer: &mut Renderer, theme: &Theme, style: &Style, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle, ) { self.content.as_widget().draw( &tree.children[0], renderer, theme, style, layout, cursor, viewport, ); } fn diff(&mut self, tree: &mut Tree) { tree.diff_children(std::slice::from_mut(&mut self.content)); } fn operate( &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { self.content .as_widget_mut() .operate(&mut tree.children[0], layout, renderer, operation); } fn update( &mut self, tree: &mut Tree, event: &Event, layout: Layout<'_>, cursor: Cursor, renderer: &Renderer, shell: &mut Shell<'_, Message>, viewport: &Rectangle, ) { self.content.as_widget_mut().update( &mut tree.children[0], event, layout, cursor, renderer, shell, viewport, ); if shell.is_event_captured() { return; } match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Back)) => { if let Some(on_back_click) = &self.on_back_click { shell.publish(on_back_click.clone()); shell.capture_event(); } } Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Forward)) => { if let Some(on_forward_click) = &self.on_forward_click { shell.publish(on_forward_click.clone()); shell.capture_event(); } } _ => {} } } fn mouse_interaction( &self, tree: &Tree, layout: Layout<'_>, cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( &tree.children[0], layout, cursor, viewport, renderer, ) } fn overlay<'b>( &'b mut self, tree: &'b mut Tree, layout: Layout<'b>, renderer: &Renderer, viewport: &Rectangle, translation: Vector, ) -> Option> { self.content.as_widget_mut().overlay( &mut tree.children[0], layout, renderer, viewport, translation, ) } }