summaryrefslogtreecommitdiffstats
path: root/lazy
diff options
context:
space:
mode:
Diffstat (limited to 'lazy')
-rw-r--r--lazy/Cargo.toml4
-rw-r--r--lazy/src/component.rs68
-rw-r--r--lazy/src/lazy.rs29
-rw-r--r--lazy/src/responsive.rs47
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();