//! Keep behavior field state within one editing session and reset it on replacement. use iced::advanced::widget::{Operation, Tree, tree}; use iced::advanced::{Clipboard, Layout, Shell, Widget, layout, overlay, renderer}; use iced::{Element, Event, Length, Rectangle, Size, Theme, Vector, mouse}; use oa_core::Id; struct Identity(Id); struct Session<'a, Message, R: renderer::Renderer> { identity: Id, content: Element<'a, Message, Theme, R>, } pub(super) fn reset_on_change<'a, Message: 'a, R: renderer::Renderer + 'a>( identity: Id, content: impl Into>, ) -> Element<'a, Message, Theme, R> { Element::new(Session { identity, content: content.into(), }) } impl Widget for Session<'_, Message, R> { fn tag(&self) -> tree::Tag { tree::Tag::of::() } fn state(&self) -> tree::State { tree::State::new(Identity(self.identity)) } fn children(&self) -> Vec { vec![Tree::new(self.content.as_widget())] } fn diff(&self, tree: &mut Tree) { let retained = tree.state.downcast_mut::(); if retained.0 != self.identity { retained.0 = self.identity; // Iced's keyed column preserves same-length child replacements. // An editing-session replacement must instead get fresh field state. tree.children = self.children(); } else { tree.diff_children(std::slice::from_ref(&self.content)); } } fn size(&self) -> Size { self.content.as_widget().size() } fn layout(&mut self, tree: &mut Tree, renderer: &R, limits: &layout::Limits) -> layout::Node { self.content .as_widget_mut() .layout(&mut tree.children[0], renderer, limits) } fn operate( &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &R, 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: mouse::Cursor, renderer: &R, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, viewport: &Rectangle, ) { self.content.as_widget_mut().update( &mut tree.children[0], event, layout, cursor, renderer, clipboard, shell, viewport, ); } fn draw( &self, tree: &Tree, renderer: &mut R, theme: &Theme, style: &renderer::Style, layout: Layout<'_>, cursor: mouse::Cursor, viewport: &Rectangle, ) { self.content.as_widget().draw( &tree.children[0], renderer, theme, style, layout, cursor, viewport, ); } fn mouse_interaction( &self, tree: &Tree, layout: Layout<'_>, cursor: mouse::Cursor, viewport: &Rectangle, renderer: &R, ) -> 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: &R, viewport: &Rectangle, translation: Vector, ) -> Option> { self.content.as_widget_mut().overlay( &mut tree.children[0], layout, renderer, viewport, translation, ) } }