From a92307890fcc3a567ec3d1b1cffebb59ae98991e Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Sun, 5 Dec 2021 23:27:08 -0800 Subject: feat: enable overlay in component --- lazy/src/component.rs | 392 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 351 insertions(+), 41 deletions(-) (limited to 'lazy/src/component.rs') diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 698f1796..bdd0addb 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -4,10 +4,12 @@ use iced_native::mouse; use iced_native::overlay; use iced_native::renderer; use iced_native::{ - Clipboard, Element, Hasher, Length, Point, Rectangle, Shell, Widget, + Clipboard, Element, Hasher, Length, Point, Rectangle, Shell, Size, Widget, }; use ouroboros::self_referencing; +use std::cell::RefCell; +use std::hash::Hash; use std::marker::PhantomData; pub fn view<'a, C, Message, Renderer>( @@ -19,16 +21,22 @@ where Renderer: iced_native::Renderer + 'a, { Element::new(Instance { - state: Some( + state: RefCell::new(Some( StateBuilder { component: Box::new(component), - cache_builder: |state| Cache { - element: state.view(), - message: PhantomData, + cache_builder: |state| { + Some( + CacheBuilder { + element: state.view(), + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ) }, } .build(), - ), + )), }) } @@ -41,7 +49,7 @@ pub trait Component { } struct Instance<'a, Message, Renderer, Event> { - state: Option>, + state: RefCell>>, } #[self_referencing] @@ -50,12 +58,17 @@ struct State<'a, Message: 'a, Renderer: 'a, Event: 'a> { #[borrows(mut component)] #[covariant] - cache: Cache<'this, Message, Renderer, Event>, + cache: Option>, } -struct Cache<'a, Message, Renderer, Event> { +#[self_referencing] +struct Cache<'a, Message, Renderer: 'a, Event: 'a> { element: Element<'a, Event, Renderer>, message: PhantomData, + + #[borrows(mut element)] + #[covariant] + overlay: Option>, } impl<'a, Message, Renderer, Event> Widget @@ -64,11 +77,47 @@ where Renderer: iced_native::Renderer, { fn width(&self) -> Length { - self.state.as_ref().unwrap().borrow_cache().element.width() + self.state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + let width = element.width(); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + + width + }) } fn height(&self) -> Length { - self.state.as_ref().unwrap().borrow_cache().element.height() + self.state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + let height = element.height(); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + + height + }) } fn layout( @@ -77,11 +126,24 @@ where limits: &layout::Limits, ) -> layout::Node { self.state - .as_ref() + .borrow_mut() + .as_mut() .unwrap() - .borrow_cache() - .element - .layout(renderer, limits) + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + let layout = element.layout(renderer, limits); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + + layout + }) } fn on_event( @@ -96,16 +158,32 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - let event_status = - self.state.as_mut().unwrap().with_cache_mut(|cache| { - cache.element.on_event( + let event_status = self + .state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + let mut element = cache.take().unwrap().into_heads().element; + let event_status = element.on_event( event, layout, cursor_position, renderer, clipboard, &mut local_shell, - ) + ); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + + event_status }); if !local_messages.is_empty() { @@ -119,12 +197,18 @@ where shell.publish(message); } - self.state = Some( + *self.state.borrow_mut() = Some( StateBuilder { component, - cache_builder: |state| Cache { - element: state.view(), - message: PhantomData, + cache_builder: |state| { + Some( + CacheBuilder { + element: state.view(), + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ) }, } .build(), @@ -144,22 +228,49 @@ where cursor_position: Point, viewport: &Rectangle, ) { - self.state.as_ref().unwrap().borrow_cache().element.draw( - renderer, - style, - layout, - cursor_position, - viewport, - ) + self.state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + element.draw( + renderer, + style, + layout, + cursor_position, + viewport, + ); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + }) } fn hash_layout(&self, state: &mut Hasher) { self.state - .as_ref() + .borrow_mut() + .as_mut() .unwrap() - .borrow_cache() - .element - .hash_layout(state) + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + element.hash_layout(state); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + }) } fn mouse_interaction( @@ -169,18 +280,217 @@ where viewport: &Rectangle, ) -> mouse::Interaction { self.state - .as_ref() + .borrow_mut() + .as_mut() .unwrap() - .borrow_cache() - .element - .mouse_interaction(layout, cursor_position, viewport) + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + let mouse_interaction = element.mouse_interaction( + layout, + cursor_position, + viewport, + ); + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |_| None, + } + .build(), + ); + + mouse_interaction + }) } fn overlay( &mut self, - _layout: Layout<'_>, + layout: Layout<'_>, ) -> Option> { - // TODO: Rethink overlay composability - None + let has_overlay = self + .state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + let element = cache.take().unwrap().into_heads().element; + + *cache = Some( + CacheBuilder { + element, + message: PhantomData, + overlay_builder: |element| element.overlay(layout), + } + .build(), + ); + + cache.as_ref().unwrap().borrow_overlay().is_some() + }); + + let Self { state, .. } = self; + + has_overlay.then(|| { + overlay::Element::new( + layout.position(), + Box::new(Overlay { state }), + ) + }) + } +} + +struct Overlay<'a, 'b, Message, Event, Renderer> { + state: &'b RefCell>>, +} + +impl<'a, 'b, Message, Event, Renderer> overlay::Overlay + for Overlay<'a, 'b, Message, Event, Renderer> +where + Renderer: iced_native::Renderer, +{ + fn layout( + &self, + renderer: &Renderer, + bounds: Size, + position: Point, + ) -> layout::Node { + self.state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + cache.as_mut().unwrap().with_overlay_mut(|overlay| { + *overlay = overlay.take().map(|x| { + let vector = position - x.position(); + x.translate(vector) + }); + overlay + .as_mut() + .map(|overlay| overlay.layout(renderer, bounds)) + .unwrap_or_else(|| layout::Node::new(Size::ZERO)) + }) + }) + } + + fn draw( + &self, + renderer: &mut Renderer, + style: &renderer::Style, + layout: Layout<'_>, + cursor_position: Point, + ) { + self.state.borrow().as_ref().unwrap().with_cache(|cache| { + if let Some(overlay) = + cache.as_ref().unwrap().borrow_overlay().as_ref() + { + overlay.draw(renderer, style, layout, cursor_position); + } + }) + } + + fn mouse_interaction( + &self, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, + ) -> mouse::Interaction { + self.state.borrow().as_ref().unwrap().with_cache(|cache| { + cache + .as_ref() + .unwrap() + .borrow_overlay() + .as_ref() + .map(|overlay| { + overlay.mouse_interaction(layout, cursor_position, viewport) + }) + .unwrap_or(mouse::Interaction::default()) + }) + } + + fn hash_layout(&self, state: &mut Hasher, position: Point) { + struct Marker; + std::any::TypeId::of::().hash(state); + + (position.x as u32).hash(state); + (position.y as u32).hash(state); + + self.state.borrow().as_ref().unwrap().with_cache(|cache| { + if let Some(overlay) = + cache.as_ref().unwrap().borrow_overlay().as_ref() + { + overlay.hash_layout(state); + } + }) + } + + fn on_event( + &mut self, + event: iced_native::Event, + layout: Layout<'_>, + cursor_position: Point, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, Message>, + ) -> iced_native::event::Status { + let mut local_messages = Vec::new(); + let mut local_shell = Shell::new(&mut local_messages); + + let event_status = self + .state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + cache.as_mut().unwrap().with_overlay_mut(|overlay| { + overlay + .as_mut() + .map(|overlay| { + overlay.on_event( + event, + layout, + cursor_position, + renderer, + clipboard, + &mut local_shell, + ) + }) + .unwrap_or(iced_native::event::Status::Ignored) + }) + }); + + if !local_messages.is_empty() { + let mut component = + self.state.take().unwrap().into_heads().component; + + for message in local_messages + .into_iter() + .filter_map(|message| component.update(message)) + { + shell.publish(message); + } + + *self.state.borrow_mut() = Some( + StateBuilder { + component, + cache_builder: |state| { + Some( + CacheBuilder { + element: state.view(), + message: PhantomData, + overlay_builder: |element| { + element.overlay(layout) + }, + } + .build(), + ) + }, + } + .build(), + ); + + shell.invalidate_layout(); + } + + event_status } } -- cgit From 48b2264bc6026e4b4b00791fef5ce34d464abc17 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 13 Dec 2021 17:46:39 +0700 Subject: Simplify `component` implementation in `iced_lazy` --- lazy/src/component.rs | 332 +++++++++++++++++++------------------------------- 1 file changed, 122 insertions(+), 210 deletions(-) (limited to 'lazy/src/component.rs') diff --git a/lazy/src/component.rs b/lazy/src/component.rs index bdd0addb..9b036b61 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -71,19 +71,25 @@ struct Cache<'a, Message, Renderer: 'a, Event: 'a> { overlay: Option>, } -impl<'a, Message, Renderer, Event> Widget - for Instance<'a, Message, Renderer, Event> -where - Renderer: iced_native::Renderer, -{ - fn width(&self) -> Length { +impl<'a, Message, Renderer, Event> Instance<'a, Message, Renderer, Event> { + fn with_element( + &self, + f: impl FnOnce(&Element<'_, Event, Renderer>) -> T, + ) -> T { + self.with_element_mut(|element| f(element)) + } + + fn with_element_mut( + &self, + f: impl FnOnce(&mut Element<'_, Event, Renderer>) -> T, + ) -> T { self.state .borrow_mut() .as_mut() .unwrap() .with_cache_mut(|cache| { - let element = cache.take().unwrap().into_heads().element; - let width = element.width(); + let mut element = cache.take().unwrap().into_heads().element; + let result = f(&mut element); *cache = Some( CacheBuilder { @@ -94,30 +100,22 @@ where .build(), ); - width + result }) } +} - fn height(&self) -> Length { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - let element = cache.take().unwrap().into_heads().element; - let height = element.height(); - - *cache = Some( - CacheBuilder { - element, - message: PhantomData, - overlay_builder: |_| None, - } - .build(), - ); +impl<'a, Message, Renderer, Event> Widget + for Instance<'a, Message, Renderer, Event> +where + Renderer: iced_native::Renderer, +{ + fn width(&self) -> Length { + self.with_element(|element| element.width()) + } - height - }) + fn height(&self) -> Length { + self.with_element(|element| element.height()) } fn layout( @@ -125,25 +123,7 @@ where renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - let element = cache.take().unwrap().into_heads().element; - let layout = element.layout(renderer, limits); - - *cache = Some( - CacheBuilder { - element, - message: PhantomData, - overlay_builder: |_| None, - } - .build(), - ); - - layout - }) + self.with_element(|element| element.layout(renderer, limits)) } fn on_event( @@ -158,37 +138,25 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - let event_status = self - .state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - let mut element = cache.take().unwrap().into_heads().element; - let event_status = element.on_event( - event, - layout, - cursor_position, - renderer, - clipboard, - &mut local_shell, - ); - - *cache = Some( - CacheBuilder { - element, - message: PhantomData, - overlay_builder: |_| None, - } - .build(), - ); - - event_status - }); + let event_status = self.with_element_mut(|element| { + element.on_event( + event, + layout, + cursor_position, + renderer, + clipboard, + &mut local_shell, + ) + }); if !local_messages.is_empty() { - let mut component = - self.state.take().unwrap().into_heads().component; + let mut component = self + .state + .borrow_mut() + .take() + .unwrap() + .into_heads() + .component; for message in local_messages .into_iter() @@ -228,49 +196,15 @@ where cursor_position: Point, viewport: &Rectangle, ) { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - let element = cache.take().unwrap().into_heads().element; - element.draw( - renderer, - style, - layout, - cursor_position, - viewport, - ); - - *cache = Some( - CacheBuilder { - element, - message: PhantomData, - overlay_builder: |_| None, - } - .build(), - ); - }) + self.with_element(|element| { + element.draw(renderer, style, layout, cursor_position, viewport); + }); } fn hash_layout(&self, state: &mut Hasher) { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - let element = cache.take().unwrap().into_heads().element; - element.hash_layout(state); - - *cache = Some( - CacheBuilder { - element, - message: PhantomData, - overlay_builder: |_| None, - } - .build(), - ); - }) + self.with_element(|element| { + element.hash_layout(state); + }); } fn mouse_interaction( @@ -279,29 +213,9 @@ where cursor_position: Point, viewport: &Rectangle, ) -> mouse::Interaction { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - let element = cache.take().unwrap().into_heads().element; - let mouse_interaction = element.mouse_interaction( - layout, - cursor_position, - viewport, - ); - - *cache = Some( - CacheBuilder { - element, - message: PhantomData, - overlay_builder: |_| None, - } - .build(), - ); - - mouse_interaction - }) + self.with_element(|element| { + element.mouse_interaction(layout, cursor_position, viewport) + }) } fn overlay( @@ -328,23 +242,60 @@ where cache.as_ref().unwrap().borrow_overlay().is_some() }); - let Self { state, .. } = self; - has_overlay.then(|| { overlay::Element::new( layout.position(), - Box::new(Overlay { state }), + Box::new(Overlay { instance: self }), ) }) } } -struct Overlay<'a, 'b, Message, Event, Renderer> { - state: &'b RefCell>>, +struct Overlay<'a, 'b, Message, Renderer, Event> { + instance: &'b mut Instance<'a, Message, Renderer, Event>, } -impl<'a, 'b, Message, Event, Renderer> overlay::Overlay - for Overlay<'a, 'b, Message, Event, Renderer> +impl<'a, 'b, Message, Renderer, Event> + Overlay<'a, 'b, Message, Renderer, Event> +{ + fn with_overlay( + &self, + f: impl FnOnce(&overlay::Element<'_, Event, Renderer>) -> T, + ) -> T { + f(self + .instance + .state + .borrow() + .as_ref() + .unwrap() + .borrow_cache() + .as_ref() + .unwrap() + .borrow_overlay() + .as_ref() + .unwrap()) + } + + fn with_overlay_mut( + &self, + f: impl FnOnce(&mut overlay::Element<'_, Event, Renderer>) -> T, + ) -> T { + self.instance + .state + .borrow_mut() + .as_mut() + .unwrap() + .with_cache_mut(|cache| { + cache + .as_mut() + .unwrap() + .with_overlay_mut(|overlay| f(overlay.as_mut().unwrap())) + }) + } +} + +impl<'a, 'b, Message, Renderer, Event> overlay::Overlay + for Overlay<'a, 'b, Message, Renderer, Event> where Renderer: iced_native::Renderer, { @@ -354,22 +305,11 @@ where bounds: Size, position: Point, ) -> layout::Node { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - cache.as_mut().unwrap().with_overlay_mut(|overlay| { - *overlay = overlay.take().map(|x| { - let vector = position - x.position(); - x.translate(vector) - }); - overlay - .as_mut() - .map(|overlay| overlay.layout(renderer, bounds)) - .unwrap_or_else(|| layout::Node::new(Size::ZERO)) - }) - }) + self.with_overlay(|overlay| { + let vector = position - overlay.position(); + + overlay.layout(renderer, bounds).translate(vector) + }) } fn draw( @@ -379,12 +319,8 @@ where layout: Layout<'_>, cursor_position: Point, ) { - self.state.borrow().as_ref().unwrap().with_cache(|cache| { - if let Some(overlay) = - cache.as_ref().unwrap().borrow_overlay().as_ref() - { - overlay.draw(renderer, style, layout, cursor_position); - } + self.with_overlay(|overlay| { + overlay.draw(renderer, style, layout, cursor_position); }) } @@ -394,16 +330,8 @@ where cursor_position: Point, viewport: &Rectangle, ) -> mouse::Interaction { - self.state.borrow().as_ref().unwrap().with_cache(|cache| { - cache - .as_ref() - .unwrap() - .borrow_overlay() - .as_ref() - .map(|overlay| { - overlay.mouse_interaction(layout, cursor_position, viewport) - }) - .unwrap_or(mouse::Interaction::default()) + self.with_overlay(|overlay| { + overlay.mouse_interaction(layout, cursor_position, viewport) }) } @@ -414,13 +342,9 @@ where (position.x as u32).hash(state); (position.y as u32).hash(state); - self.state.borrow().as_ref().unwrap().with_cache(|cache| { - if let Some(overlay) = - cache.as_ref().unwrap().borrow_overlay().as_ref() - { - overlay.hash_layout(state); - } - }) + self.with_overlay(|overlay| { + overlay.hash_layout(state); + }); } fn on_event( @@ -435,32 +359,20 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - let event_status = self - .state - .borrow_mut() - .as_mut() - .unwrap() - .with_cache_mut(|cache| { - cache.as_mut().unwrap().with_overlay_mut(|overlay| { - overlay - .as_mut() - .map(|overlay| { - overlay.on_event( - event, - layout, - cursor_position, - renderer, - clipboard, - &mut local_shell, - ) - }) - .unwrap_or(iced_native::event::Status::Ignored) - }) - }); + let event_status = self.with_overlay_mut(|overlay| { + overlay.on_event( + event, + layout, + cursor_position, + renderer, + clipboard, + &mut local_shell, + ) + }); if !local_messages.is_empty() { let mut component = - self.state.take().unwrap().into_heads().component; + self.instance.state.take().unwrap().into_heads().component; for message in local_messages .into_iter() @@ -469,7 +381,7 @@ where shell.publish(message); } - *self.state.borrow_mut() = Some( + self.instance.state = RefCell::new(Some( StateBuilder { component, cache_builder: |state| { @@ -486,7 +398,7 @@ where }, } .build(), - ); + )); shell.invalidate_layout(); } -- cgit From aa09bd4a981cfe0e11a21220193e823f48cdf450 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Mon, 13 Dec 2021 16:12:47 -0800 Subject: fix: process component overlay events together with those of the original element --- lazy/src/component.rs | 51 ++++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) (limited to 'lazy/src/component.rs') diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 9b036b61..998e2198 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -24,6 +24,7 @@ where state: RefCell::new(Some( StateBuilder { component: Box::new(component), + overlay_events: None, cache_builder: |state| { Some( CacheBuilder { @@ -55,6 +56,7 @@ struct Instance<'a, Message, Renderer, Event> { #[self_referencing] struct State<'a, Message: 'a, Renderer: 'a, Event: 'a> { component: Box + 'a>, + overlay_events: Option>, #[borrows(mut component)] #[covariant] @@ -103,6 +105,17 @@ impl<'a, Message, Renderer, Event> Instance<'a, Message, Renderer, Event> { result }) } + + fn with_overlay_events_mut( + &self, + f: impl FnOnce(&mut Option>) -> T, + ) -> T { + self.state + .borrow_mut() + .as_mut() + .unwrap() + .with_overlay_events_mut(f) + } } impl<'a, Message, Renderer, Event> Widget @@ -135,7 +148,9 @@ where clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - let mut local_messages = Vec::new(); + let mut local_messages = self + .with_overlay_events_mut(|overlay_events| overlay_events.take()) + .unwrap_or_default(); let mut local_shell = Shell::new(&mut local_messages); let event_status = self.with_element_mut(|element| { @@ -168,6 +183,7 @@ where *self.state.borrow_mut() = Some( StateBuilder { component, + overlay_events: None, cache_builder: |state| { Some( CacheBuilder { @@ -371,36 +387,9 @@ where }); if !local_messages.is_empty() { - let mut component = - self.instance.state.take().unwrap().into_heads().component; - - for message in local_messages - .into_iter() - .filter_map(|message| component.update(message)) - { - shell.publish(message); - } - - self.instance.state = RefCell::new(Some( - StateBuilder { - component, - cache_builder: |state| { - Some( - CacheBuilder { - element: state.view(), - message: PhantomData, - overlay_builder: |element| { - element.overlay(layout) - }, - } - .build(), - ) - }, - } - .build(), - )); - - shell.invalidate_layout(); + self.instance.with_overlay_events_mut(|overlay_events| { + *overlay_events = Some(local_messages) + }); } event_status -- cgit From 042a294448e0826d70d97978925ff05043225077 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Fri, 17 Dec 2021 08:36:05 -0800 Subject: Revert "fix: process component overlay events together with those of the original element" This reverts commit aa09bd4a981cfe0e11a21220193e823f48cdf450. --- lazy/src/component.rs | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'lazy/src/component.rs') diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 998e2198..9b036b61 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -24,7 +24,6 @@ where state: RefCell::new(Some( StateBuilder { component: Box::new(component), - overlay_events: None, cache_builder: |state| { Some( CacheBuilder { @@ -56,7 +55,6 @@ struct Instance<'a, Message, Renderer, Event> { #[self_referencing] struct State<'a, Message: 'a, Renderer: 'a, Event: 'a> { component: Box + 'a>, - overlay_events: Option>, #[borrows(mut component)] #[covariant] @@ -105,17 +103,6 @@ impl<'a, Message, Renderer, Event> Instance<'a, Message, Renderer, Event> { result }) } - - fn with_overlay_events_mut( - &self, - f: impl FnOnce(&mut Option>) -> T, - ) -> T { - self.state - .borrow_mut() - .as_mut() - .unwrap() - .with_overlay_events_mut(f) - } } impl<'a, Message, Renderer, Event> Widget @@ -148,9 +135,7 @@ where clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - let mut local_messages = self - .with_overlay_events_mut(|overlay_events| overlay_events.take()) - .unwrap_or_default(); + let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); let event_status = self.with_element_mut(|element| { @@ -183,7 +168,6 @@ where *self.state.borrow_mut() = Some( StateBuilder { component, - overlay_events: None, cache_builder: |state| { Some( CacheBuilder { @@ -387,9 +371,36 @@ where }); if !local_messages.is_empty() { - self.instance.with_overlay_events_mut(|overlay_events| { - *overlay_events = Some(local_messages) - }); + let mut component = + self.instance.state.take().unwrap().into_heads().component; + + for message in local_messages + .into_iter() + .filter_map(|message| component.update(message)) + { + shell.publish(message); + } + + self.instance.state = RefCell::new(Some( + StateBuilder { + component, + cache_builder: |state| { + Some( + CacheBuilder { + element: state.view(), + message: PhantomData, + overlay_builder: |element| { + element.overlay(layout) + }, + } + .build(), + ) + }, + } + .build(), + )); + + shell.invalidate_layout(); } event_status -- cgit From 44c0d75953984b0b31ac723bc040c016f572244d Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Fri, 17 Dec 2021 08:46:18 -0800 Subject: fix: drop remaining component overlay events if closed during event batch processing --- lazy/src/component.rs | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'lazy/src/component.rs') diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 9b036b61..787adc10 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -258,12 +258,11 @@ struct Overlay<'a, 'b, Message, Renderer, Event> { impl<'a, 'b, Message, Renderer, Event> Overlay<'a, 'b, Message, Renderer, Event> { - fn with_overlay( + fn with_overlay_maybe( &self, f: impl FnOnce(&overlay::Element<'_, Event, Renderer>) -> T, - ) -> T { - f(self - .instance + ) -> Option { + self.instance .state .borrow() .as_ref() @@ -273,13 +272,13 @@ impl<'a, 'b, Message, Renderer, Event> .unwrap() .borrow_overlay() .as_ref() - .unwrap()) + .map(f) } - fn with_overlay_mut( + fn with_overlay_mut_maybe( &self, f: impl FnOnce(&mut overlay::Element<'_, Event, Renderer>) -> T, - ) -> T { + ) -> Option { self.instance .state .borrow_mut() @@ -289,7 +288,7 @@ impl<'a, 'b, Message, Renderer, Event> cache .as_mut() .unwrap() - .with_overlay_mut(|overlay| f(overlay.as_mut().unwrap())) + .with_overlay_mut(|overlay| overlay.as_mut().map(f)) }) } } @@ -305,11 +304,12 @@ where bounds: Size, position: Point, ) -> layout::Node { - self.with_overlay(|overlay| { + self.with_overlay_maybe(|overlay| { let vector = position - overlay.position(); overlay.layout(renderer, bounds).translate(vector) }) + .unwrap_or_default() } fn draw( @@ -319,9 +319,9 @@ where layout: Layout<'_>, cursor_position: Point, ) { - self.with_overlay(|overlay| { + self.with_overlay_maybe(|overlay| { overlay.draw(renderer, style, layout, cursor_position); - }) + }); } fn mouse_interaction( @@ -330,9 +330,10 @@ where cursor_position: Point, viewport: &Rectangle, ) -> mouse::Interaction { - self.with_overlay(|overlay| { + self.with_overlay_maybe(|overlay| { overlay.mouse_interaction(layout, cursor_position, viewport) }) + .unwrap_or_default() } fn hash_layout(&self, state: &mut Hasher, position: Point) { @@ -342,7 +343,7 @@ where (position.x as u32).hash(state); (position.y as u32).hash(state); - self.with_overlay(|overlay| { + self.with_overlay_maybe(|overlay| { overlay.hash_layout(state); }); } @@ -359,16 +360,18 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - let event_status = self.with_overlay_mut(|overlay| { - overlay.on_event( - event, - layout, - cursor_position, - renderer, - clipboard, - &mut local_shell, - ) - }); + let event_status = self + .with_overlay_mut_maybe(|overlay| { + overlay.on_event( + event, + layout, + cursor_position, + renderer, + clipboard, + &mut local_shell, + ) + }) + .unwrap_or_else(|| iced_native::event::Status::Ignored); if !local_messages.is_empty() { let mut component = -- cgit