diff options
author | 2023-01-10 16:09:15 -0800 | |
---|---|---|
committer | 2023-01-10 21:35:42 -0800 | |
commit | 2e3a69be31aa07878b0139146cd113a787731393 (patch) | |
tree | 60f82a4c49aed7559f59124d34baf2b0858b8ac9 /lazy | |
parent | 7ccd87c36b54e0d53f65f5774f140a0528ae4504 (diff) | |
download | iced-2e3a69be31aa07878b0139146cd113a787731393.tar.gz iced-2e3a69be31aa07878b0139146cd113a787731393.tar.bz2 iced-2e3a69be31aa07878b0139146cd113a787731393.zip |
fix: `Lazy` widget
Diffstat (limited to 'lazy')
-rw-r--r-- | lazy/src/lazy.rs | 120 |
1 files changed, 75 insertions, 45 deletions
diff --git a/lazy/src/lazy.rs b/lazy/src/lazy.rs index ec35e8f0..16709f8d 100644 --- a/lazy/src/lazy.rs +++ b/lazy/src/lazy.rs @@ -9,16 +9,17 @@ use iced_native::Element; use iced_native::{Clipboard, Hasher, Length, Point, Rectangle, Shell, Size}; use ouroboros::self_referencing; -use std::cell::{Ref, RefCell, RefMut}; +use std::cell::RefCell; use std::hash::{Hash, Hasher as H}; -use std::marker::PhantomData; use std::rc::Rc; #[allow(missing_debug_implementations)] pub struct Lazy<'a, Message, Renderer, Dependency, View> { dependency: Dependency, view: Box<dyn Fn() -> View + 'a>, - element: RefCell<Option<Rc<RefCell<Element<'static, Message, Renderer>>>>>, + element: RefCell< + Option<Rc<RefCell<Option<Element<'static, Message, Renderer>>>>>, + >, } impl<'a, Message, Renderer, Dependency, View> @@ -37,21 +38,35 @@ where fn with_element<T>( &self, - f: impl FnOnce(Ref<Element<Message, Renderer>>) -> T, + f: impl FnOnce(&Element<Message, Renderer>) -> T, ) -> T { - f(self.element.borrow().as_ref().unwrap().borrow()) + f(self + .element + .borrow() + .as_ref() + .unwrap() + .borrow() + .as_ref() + .unwrap()) } fn with_element_mut<T>( &self, - f: impl FnOnce(RefMut<Element<Message, Renderer>>) -> T, + f: impl FnOnce(&mut Element<Message, Renderer>) -> T, ) -> T { - f(self.element.borrow().as_ref().unwrap().borrow_mut()) + f(self + .element + .borrow() + .as_ref() + .unwrap() + .borrow_mut() + .as_mut() + .unwrap()) } } struct Internal<Message, Renderer> { - element: Rc<RefCell<Element<'static, Message, Renderer>>>, + element: Rc<RefCell<Option<Element<'static, Message, Renderer>>>>, hash: u64, } @@ -73,7 +88,7 @@ where self.dependency.hash(&mut hasher); let hash = hasher.finish(); - let element = Rc::new(RefCell::new((self.view)().into())); + let element = Rc::new(RefCell::new(Some((self.view)().into()))); (*self.element.borrow_mut()) = Some(element.clone()); @@ -81,9 +96,7 @@ where } fn children(&self) -> Vec<Tree> { - vec![Tree::new( - self.element.borrow().as_ref().unwrap().borrow().as_widget(), - )] + self.with_element(|element| vec![Tree::new(element.as_widget())]) } fn diff(&self, tree: &mut Tree) { @@ -97,12 +110,12 @@ where current.hash = new_hash; let element = (self.view)().into(); - current.element = Rc::new(RefCell::new(element)); + current.element = Rc::new(RefCell::new(Some(element))); (*self.element.borrow_mut()) = Some(current.element.clone()); - tree.diff_children(std::slice::from_ref( - &self.element.borrow().as_ref().unwrap().borrow().as_widget(), - )); + self.with_element(|element| { + tree.diff_children(std::slice::from_ref(&element.as_widget())) + }); } else { (*self.element.borrow_mut()) = Some(current.element.clone()); } @@ -153,7 +166,7 @@ where clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - self.with_element_mut(|mut element| { + self.with_element_mut(|element| { element.as_widget_mut().on_event( &mut tree.children[0], event, @@ -214,23 +227,27 @@ where layout: Layout<'_>, renderer: &Renderer, ) -> Option<overlay::Element<'_, Message, Renderer>> { - let overlay = OverlayBuilder { - cached: self, - tree: &mut tree.children[0], - types: PhantomData, - overlay_builder: |cached, tree| { - Rc::get_mut(cached.element.get_mut().as_mut().unwrap()) + let overlay = Overlay(Some( + InnerBuilder { + cell: self.element.borrow().as_ref().unwrap().clone(), + element: self + .element + .borrow() + .as_ref() .unwrap() - .get_mut() - .as_widget_mut() - .overlay(tree, layout, renderer) - }, - } - .build(); - - let has_overlay = overlay.with_overlay(|overlay| { - overlay.as_ref().map(overlay::Element::position) - }); + .borrow_mut() + .take() + .unwrap(), + tree: &mut tree.children[0], + overlay_builder: |element, tree| { + element.as_widget_mut().overlay(tree, layout, renderer) + }, + } + .build(), + )); + + let has_overlay = overlay + .with_overlay_maybe(|overlay| overlay::Element::position(overlay)); has_overlay .map(|position| overlay::Element::new(position, Box::new(overlay))) @@ -238,37 +255,50 @@ where } #[self_referencing] -struct Overlay<'a, 'b, Message, Renderer, Dependency, View> { - cached: &'a mut Lazy<'b, Message, Renderer, Dependency, View>, +struct Inner<'a, Message, Renderer> +where + Message: 'a, + Renderer: 'a, +{ + cell: Rc<RefCell<Option<Element<'static, Message, Renderer>>>>, + element: Element<'static, Message, Renderer>, tree: &'a mut Tree, - types: PhantomData<(Message, Dependency, View)>, - #[borrows(mut cached, mut tree)] + #[borrows(mut element, mut tree)] #[covariant] overlay: Option<overlay::Element<'this, Message, Renderer>>, } -impl<'a, 'b, Message, Renderer, Dependency, View> - Overlay<'a, 'b, Message, Renderer, Dependency, View> -{ +struct Overlay<'a, Message, Renderer>(Option<Inner<'a, Message, Renderer>>); + +impl<'a, Message, Renderer> Drop for Overlay<'a, Message, Renderer> { + fn drop(&mut self) { + let heads = self.0.take().unwrap().into_heads(); + (*heads.cell.borrow_mut()) = Some(heads.element); + } +} + +impl<'a, Message, Renderer> Overlay<'a, Message, Renderer> { fn with_overlay_maybe<T>( &self, f: impl FnOnce(&overlay::Element<'_, Message, Renderer>) -> T, ) -> Option<T> { - self.borrow_overlay().as_ref().map(f) + self.0.as_ref().unwrap().borrow_overlay().as_ref().map(f) } fn with_overlay_mut_maybe<T>( &mut self, f: impl FnOnce(&mut overlay::Element<'_, Message, Renderer>) -> T, ) -> Option<T> { - self.with_overlay_mut(|overlay| overlay.as_mut().map(f)) + self.0 + .as_mut() + .unwrap() + .with_overlay_mut(|overlay| overlay.as_mut().map(f)) } } -impl<'a, 'b, Message, Renderer, Dependency, View> - overlay::Overlay<Message, Renderer> - for Overlay<'a, 'b, Message, Renderer, Dependency, View> +impl<'a, Message, Renderer> overlay::Overlay<Message, Renderer> + for Overlay<'a, Message, Renderer> where Renderer: iced_native::Renderer, { |