From ff2519b1d43d481987351a83b6dd7237524c21f0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 27 Jul 2022 06:49:20 +0200 Subject: Replace stateful widgets with new `iced_pure` API --- native/src/user_interface.rs | 103 ++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 40 deletions(-) (limited to 'native/src/user_interface.rs') diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index ef6f437e..9f3a8e21 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -4,6 +4,7 @@ use crate::event::{self, Event}; use crate::layout; use crate::mouse; use crate::renderer; +use crate::widget; use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size}; /// A set of interactive graphical elements with a specific [`Layout`]. @@ -22,6 +23,7 @@ use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size}; pub struct UserInterface<'a, Message, Renderer> { root: Element<'a, Message, Renderer>, base: layout::Node, + state: widget::Tree, overlay: Option, bounds: Size, } @@ -88,7 +90,7 @@ where pub fn build>>( root: E, bounds: Size, - _cache: Cache, + cache: Cache, renderer: &mut Renderer, ) -> Self { let root = root.into(); @@ -96,9 +98,13 @@ where let base = renderer.layout(&root, &layout::Limits::new(Size::ZERO, bounds)); + let Cache { mut state } = cache; + state.diff(root.as_widget()); + UserInterface { root, base, + state, overlay: None, bounds, } @@ -182,9 +188,12 @@ where use std::mem::ManuallyDrop; let mut state = State::Updated; - let mut manual_overlay = ManuallyDrop::new( - self.root.overlay(Layout::new(&self.base), renderer), - ); + let mut manual_overlay = + ManuallyDrop::new(self.root.as_widget().overlay( + &mut self.state, + Layout::new(&self.base), + renderer, + )); let (base_cursor, overlay_statuses) = if manual_overlay.is_some() { let bounds = self.bounds; @@ -215,9 +224,12 @@ where &layout::Limits::new(Size::ZERO, self.bounds), ); - manual_overlay = ManuallyDrop::new( - self.root.overlay(Layout::new(&self.base), renderer), - ); + manual_overlay = + ManuallyDrop::new(self.root.as_widget().overlay( + &mut self.state, + Layout::new(&self.base), + renderer, + )); if manual_overlay.is_none() { break; @@ -262,7 +274,8 @@ where let mut shell = Shell::new(messages); - let event_status = self.root.widget.on_event( + let event_status = self.root.as_widget_mut().on_event( + &mut self.state, event, Layout::new(&self.base), base_cursor, @@ -377,9 +390,11 @@ where let viewport = Rectangle::with_size(self.bounds); - let base_cursor = if let Some(overlay) = - self.root.overlay(Layout::new(&self.base), renderer) - { + let base_cursor = if let Some(overlay) = self.root.as_widget().overlay( + &mut self.state, + Layout::new(&self.base), + renderer, + ) { let overlay_layout = self .overlay .take() @@ -399,7 +414,8 @@ where cursor_position }; - self.root.widget.draw( + self.root.as_widget().draw( + &self.state, renderer, theme, style, @@ -408,7 +424,8 @@ where &viewport, ); - let base_interaction = self.root.widget.mouse_interaction( + let base_interaction = self.root.as_widget().mouse_interaction( + &self.state, Layout::new(&self.base), cursor_position, &viewport, @@ -430,32 +447,34 @@ where overlay .as_ref() .and_then(|layout| { - root.overlay(Layout::new(base), renderer).map(|overlay| { - let overlay_interaction = overlay.mouse_interaction( - Layout::new(layout), - cursor_position, - &viewport, - renderer, - ); - - let overlay_bounds = layout.bounds(); - - renderer.with_layer(overlay_bounds, |renderer| { - overlay.draw( - renderer, - theme, - style, + root.as_widget() + .overlay(&mut self.state, Layout::new(base), renderer) + .map(|overlay| { + let overlay_interaction = overlay.mouse_interaction( Layout::new(layout), cursor_position, + &viewport, + renderer, ); - }); - if overlay_bounds.contains(cursor_position) { - overlay_interaction - } else { - base_interaction - } - }) + let overlay_bounds = layout.bounds(); + + renderer.with_layer(overlay_bounds, |renderer| { + overlay.draw( + renderer, + theme, + style, + Layout::new(layout), + cursor_position, + ); + }); + + if overlay_bounds.contains(cursor_position) { + overlay_interaction + } else { + base_interaction + } + }) }) .unwrap_or(base_interaction) } @@ -463,19 +482,21 @@ where /// Relayouts and returns a new [`UserInterface`] using the provided /// bounds. pub fn relayout(self, bounds: Size, renderer: &mut Renderer) -> Self { - Self::build(self.root, bounds, Cache, renderer) + Self::build(self.root, bounds, Cache { state: self.state }, renderer) } /// Extract the [`Cache`] of the [`UserInterface`], consuming it in the /// process. pub fn into_cache(self) -> Cache { - Cache + Cache { state: self.state } } } /// Reusable data of a specific [`UserInterface`]. -#[derive(Debug, Clone)] -pub struct Cache; +#[derive(Debug)] +pub struct Cache { + state: widget::Tree, +} impl Cache { /// Creates an empty [`Cache`]. @@ -483,7 +504,9 @@ impl Cache { /// You should use this to initialize a [`Cache`] before building your first /// [`UserInterface`]. pub fn new() -> Cache { - Cache + Cache { + state: widget::Tree::empty(), + } } } -- cgit From 80688689aa4b15bc23824df899974a9094a77b07 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Jul 2022 02:46:51 +0200 Subject: Draft widget operations --- native/src/user_interface.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'native/src/user_interface.rs') diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 9f3a8e21..25557240 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -479,6 +479,27 @@ where .unwrap_or(base_interaction) } + /// Applies a [`widget::Operation`] to the [`UserInterface`]. + pub fn operate( + &mut self, + renderer: &Renderer, + operation: &mut dyn widget::Operation, + ) { + self.root + .as_widget() + .operate(Layout::new(&self.base), operation); + + if let Some(layout) = self.overlay.as_ref() { + if let Some(overlay) = self.root.as_widget().overlay( + &mut self.state, + Layout::new(&self.base), + renderer, + ) { + overlay.operate(Layout::new(layout), operation); + } + } + } + /// Relayouts and returns a new [`UserInterface`] using the provided /// bounds. pub fn relayout(self, bounds: Size, renderer: &mut Renderer) -> Self { -- cgit From 52f84e51e90db1c324310565f2aff8b7e6987cba Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 Jul 2022 03:53:47 +0200 Subject: Implement `Widget::operate` for `TextInput` --- native/src/user_interface.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'native/src/user_interface.rs') diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 25557240..42669f95 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -485,9 +485,11 @@ where renderer: &Renderer, operation: &mut dyn widget::Operation, ) { - self.root - .as_widget() - .operate(Layout::new(&self.base), operation); + self.root.as_widget().operate( + &mut self.state, + Layout::new(&self.base), + operation, + ); if let Some(layout) = self.overlay.as_ref() { if let Some(overlay) = self.root.as_widget().overlay( -- cgit From c23ed7e4a0a2b62a0d7cabe6e35d7323eac543d2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 5 Aug 2022 23:51:32 +0200 Subject: Lay out `UserInterface` after diffing --- native/src/user_interface.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'native/src/user_interface.rs') diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 42669f95..4bcf1e0c 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -95,12 +95,12 @@ where ) -> Self { let root = root.into(); - let base = - renderer.layout(&root, &layout::Limits::new(Size::ZERO, bounds)); - let Cache { mut state } = cache; state.diff(root.as_widget()); + let base = + renderer.layout(&root, &layout::Limits::new(Size::ZERO, bounds)); + UserInterface { root, base, -- cgit