diff options
Diffstat (limited to 'lazy')
-rw-r--r-- | lazy/Cargo.toml | 4 | ||||
-rw-r--r-- | lazy/src/component.rs | 68 | ||||
-rw-r--r-- | lazy/src/lazy.rs | 29 | ||||
-rw-r--r-- | lazy/src/responsive.rs | 47 |
4 files changed, 100 insertions, 48 deletions
diff --git a/lazy/Cargo.toml b/lazy/Cargo.toml index 51459148..1b26e5c9 100644 --- a/lazy/Cargo.toml +++ b/lazy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_lazy" -version = "0.2.0" +version = "0.3.0" authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] edition = "2021" description = "Lazy widgets for Iced" @@ -14,5 +14,5 @@ categories = ["gui"] ouroboros = "0.13" [dependencies.iced_native] -version = "0.6" +version = "0.7" path = "../native" diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 4f1df650..d8f21f8a 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -11,7 +11,7 @@ use iced_native::{ }; use ouroboros::self_referencing; -use std::cell::{Ref, RefCell}; +use std::cell::RefCell; use std::marker::PhantomData; /// A reusable, custom widget that uses The Elm Architecture. @@ -46,6 +46,16 @@ pub trait Component<Message, Renderer> { /// Produces the widgets of the [`Component`], which may trigger an [`Event`](Component::Event) /// on user interaction. fn view(&self, state: &Self::State) -> Element<'_, Self::Event, Renderer>; + + /// Update the [`Component`] state based on the provided [`Operation`](widget::Operation) + /// + /// By default, it does nothing. + fn operate( + &self, + _state: &mut Self::State, + _operation: &mut dyn widget::Operation<Message>, + ) { + } } /// Turns an implementor of [`Component`] into an [`Element`] that can be @@ -106,6 +116,26 @@ where ); } + fn rebuild_element_with_operation( + &self, + state: &mut S, + operation: &mut dyn widget::Operation<Message>, + ) { + let heads = self.state.borrow_mut().take().unwrap().into_heads(); + + heads.component.operate(state, operation); + + *self.state.borrow_mut() = Some( + StateBuilder { + component: heads.component, + message: PhantomData, + state: PhantomData, + element_builder: |component| Some(component.view(state)), + } + .build(), + ); + } + fn with_element<T>( &self, f: impl FnOnce(&Element<'_, Event, Renderer>) -> T, @@ -234,8 +264,14 @@ where &self, tree: &mut Tree, layout: Layout<'_>, + renderer: &Renderer, operation: &mut dyn widget::Operation<Message>, ) { + self.rebuild_element_with_operation( + tree.state.downcast_mut(), + operation, + ); + struct MapOperation<'a, B> { operation: &'a mut dyn widget::Operation<B>, } @@ -274,6 +310,7 @@ where element.as_widget().operate( &mut tree.children[0], layout, + renderer, &mut MapOperation { operation }, ); }); @@ -322,25 +359,25 @@ where } fn overlay<'b>( - &'b self, + &'b mut self, tree: &'b mut Tree, layout: Layout<'_>, renderer: &Renderer, ) -> Option<overlay::Element<'b, Message, Renderer>> { let overlay = OverlayBuilder { instance: self, - instance_ref_builder: |instance| instance.state.borrow(), tree, types: PhantomData, overlay_builder: |instance, tree| { - instance - .as_ref() - .unwrap() - .borrow_element() - .as_ref() - .unwrap() - .as_widget() - .overlay(&mut tree.children[0], layout, renderer) + instance.state.get_mut().as_mut().unwrap().with_element_mut( + move |element| { + element.as_mut().unwrap().as_widget_mut().overlay( + &mut tree.children[0], + layout, + renderer, + ) + }, + ) }, } .build(); @@ -362,15 +399,11 @@ where #[self_referencing] struct Overlay<'a, 'b, Message, Renderer, Event, S> { - instance: &'a Instance<'b, Message, Renderer, Event, S>, + instance: &'a mut Instance<'b, Message, Renderer, Event, S>, tree: &'a mut Tree, types: PhantomData<(Message, Event, S)>, - #[borrows(instance)] - #[covariant] - instance_ref: Ref<'this, Option<State<'a, Message, Renderer, Event, S>>>, - - #[borrows(instance_ref, mut tree)] + #[borrows(mut instance, mut tree)] #[covariant] overlay: Option<overlay::Element<'this, Event, Renderer>>, } @@ -514,7 +547,6 @@ where self.overlay = Some( OverlayBuilder { instance: overlay.instance, - instance_ref_builder: |instance| instance.state.borrow(), tree: overlay.tree, types: PhantomData, overlay_builder: |_, _| None, diff --git a/lazy/src/lazy.rs b/lazy/src/lazy.rs index d61cc77e..ec35e8f0 100644 --- a/lazy/src/lazy.rs +++ b/lazy/src/lazy.rs @@ -130,12 +130,14 @@ where &self, tree: &mut Tree, layout: Layout<'_>, + renderer: &Renderer, operation: &mut dyn widget::Operation<Message>, ) { self.with_element(|element| { element.as_widget().operate( &mut tree.children[0], layout, + renderer, operation, ); }); @@ -207,7 +209,7 @@ where } fn overlay<'b>( - &'b self, + &'b mut self, tree: &'b mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -216,12 +218,12 @@ where cached: self, tree: &mut tree.children[0], types: PhantomData, - element_ref_builder: |cached| cached.element.borrow(), - element_builder: |element_ref| { - element_ref.as_ref().unwrap().borrow() - }, - overlay_builder: |element, tree| { - element.as_widget().overlay(tree, layout, renderer) + overlay_builder: |cached, tree| { + Rc::get_mut(cached.element.get_mut().as_mut().unwrap()) + .unwrap() + .get_mut() + .as_widget_mut() + .overlay(tree, layout, renderer) }, } .build(); @@ -237,20 +239,11 @@ where #[self_referencing] struct Overlay<'a, 'b, Message, Renderer, Dependency, View> { - cached: &'a Lazy<'b, Message, Renderer, Dependency, View>, + cached: &'a mut Lazy<'b, Message, Renderer, Dependency, View>, tree: &'a mut Tree, types: PhantomData<(Message, Dependency, View)>, - #[borrows(cached)] - #[covariant] - element_ref: - Ref<'this, Option<Rc<RefCell<Element<'static, Message, Renderer>>>>>, - - #[borrows(element_ref)] - #[covariant] - element: Ref<'this, Element<'static, Message, Renderer>>, - - #[borrows(element, mut tree)] + #[borrows(mut cached, mut tree)] #[covariant] overlay: Option<overlay::Element<'this, Message, Renderer>>, } diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs index 0b7ae6de..945c935a 100644 --- a/lazy/src/responsive.rs +++ b/lazy/src/responsive.rs @@ -3,8 +3,8 @@ use iced_native::layout::{self, Layout}; use iced_native::mouse; use iced_native::overlay; use iced_native::renderer; -use iced_native::widget::horizontal_space; use iced_native::widget::tree::{self, Tree}; +use iced_native::widget::{self, horizontal_space}; use iced_native::{ Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget, }; @@ -142,6 +142,29 @@ where layout::Node::new(limits.max()) } + fn operate( + &self, + tree: &mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn widget::Operation<Message>, + ) { + let state = tree.state.downcast_mut::<State>(); + let mut content = self.content.borrow_mut(); + + content.resolve( + &mut state.tree.borrow_mut(), + renderer, + layout, + &self.view, + |tree, renderer, layout, element| { + element + .as_widget() + .operate(tree, layout, renderer, operation); + }, + ); + } + fn on_event( &mut self, tree: &mut Tree, @@ -235,18 +258,20 @@ where } fn overlay<'b>( - &'b self, + &'b mut self, tree: &'b mut Tree, layout: Layout<'_>, renderer: &Renderer, ) -> Option<overlay::Element<'b, Message, Renderer>> { + use std::ops::DerefMut; + let state = tree.state.downcast_ref::<State>(); let overlay = OverlayBuilder { content: self.content.borrow_mut(), tree: state.tree.borrow_mut(), types: PhantomData, - overlay_builder: |content, tree| { + overlay_builder: |content: &mut RefMut<Content<_, _>>, tree| { content.update( tree, renderer, @@ -254,16 +279,18 @@ where &self.view, ); + let Content { + element, layout, .. + } = content.deref_mut(); + let content_layout = Layout::with_offset( - layout.position() - Point::ORIGIN, - &content.layout, + layout.bounds().position() - Point::ORIGIN, + layout, ); - content.element.as_widget().overlay( - tree, - content_layout, - renderer, - ) + element + .as_widget_mut() + .overlay(tree, content_layout, renderer) }, } .build(); |