diff options
author | 2022-01-11 13:47:43 +0700 | |
---|---|---|
committer | 2022-01-11 13:47:43 +0700 | |
commit | 6ab4611a6eec9c4bb4ca1ff1bb580bb7edf49add (patch) | |
tree | c96d3eb77ffe99a580ed13efecc50d2857f1b8f0 /native | |
parent | 90c20ac46b72b6d8f735f7efd283b9d1dfecfb9d (diff) | |
download | iced-6ab4611a6eec9c4bb4ca1ff1bb580bb7edf49add.tar.gz iced-6ab4611a6eec9c4bb4ca1ff1bb580bb7edf49add.tar.bz2 iced-6ab4611a6eec9c4bb4ca1ff1bb580bb7edf49add.zip |
Invalidate widget tree from `Responsive` widget
... by introducing a new `invalidate_widgets` method to `Shell`
Diffstat (limited to 'native')
-rw-r--r-- | native/src/lib.rs | 4 | ||||
-rw-r--r-- | native/src/program/state.rs | 12 | ||||
-rw-r--r-- | native/src/shell.rs | 20 | ||||
-rw-r--r-- | native/src/user_interface.rs | 45 | ||||
-rw-r--r-- | native/src/widget/responsive.rs | 4 |
5 files changed, 63 insertions, 22 deletions
diff --git a/native/src/lib.rs b/native/src/lib.rs index 4211995f..c527a69a 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -50,6 +50,7 @@ pub mod subscription; pub mod svg; pub mod text; pub mod touch; +pub mod user_interface; pub mod widget; pub mod window; @@ -57,7 +58,6 @@ mod element; mod hasher; mod runtime; mod shell; -mod user_interface; // We disable debug capabilities on release builds unless the `debug` feature // is explicitly enabled. @@ -91,5 +91,5 @@ pub use renderer::Renderer; pub use runtime::Runtime; pub use shell::Shell; pub use subscription::Subscription; -pub use user_interface::{Cache, UserInterface}; +pub use user_interface::UserInterface; pub use widget::Widget; diff --git a/native/src/program/state.rs b/native/src/program/state.rs index 26c0eb21..cb87a628 100644 --- a/native/src/program/state.rs +++ b/native/src/program/state.rs @@ -1,8 +1,6 @@ use crate::mouse; -use crate::{ - Cache, Clipboard, Command, Debug, Event, Point, Program, Size, - UserInterface, -}; +use crate::user_interface::{self, UserInterface}; +use crate::{Clipboard, Command, Debug, Event, Point, Program, Size}; /// The execution state of a [`Program`]. It leverages caching, event /// processing, and rendering primitive storage. @@ -12,7 +10,7 @@ where P: Program + 'static, { program: P, - cache: Option<Cache>, + cache: Option<user_interface::Cache>, queued_events: Vec<Event>, queued_messages: Vec<P::Message>, mouse_interaction: mouse::Interaction, @@ -32,7 +30,7 @@ where ) -> Self { let user_interface = build_user_interface( &mut program, - Cache::default(), + user_interface::Cache::default(), renderer, bounds, debug, @@ -161,7 +159,7 @@ where fn build_user_interface<'a, P: Program>( program: &'a mut P, - cache: Cache, + cache: user_interface::Cache, renderer: &mut P::Renderer, size: Size, debug: &mut Debug, diff --git a/native/src/shell.rs b/native/src/shell.rs index e916f52d..4a0aa9c6 100644 --- a/native/src/shell.rs +++ b/native/src/shell.rs @@ -8,6 +8,7 @@ pub struct Shell<'a, Message> { messages: &'a mut Vec<Message>, is_layout_invalid: bool, + are_widgets_invalid: bool, } impl<'a, Message> Shell<'a, Message> { @@ -16,12 +17,13 @@ impl<'a, Message> Shell<'a, Message> { Self { messages, is_layout_invalid: false, + are_widgets_invalid: false, } } /// Triggers the given function if the layout is invalid, cleaning it in the /// process. - pub fn with_invalid_layout(&mut self, f: impl FnOnce()) { + pub fn revalidate_layout(&mut self, f: impl FnOnce()) { if self.is_layout_invalid { self.is_layout_invalid = false; @@ -41,6 +43,13 @@ impl<'a, Message> Shell<'a, Message> { self.is_layout_invalid = true; } + /// Invalidates the current application widgets. + /// + /// The shell will rebuild and relayout the widget tree. + pub fn invalidate_widgets(&mut self) { + self.are_widgets_invalid = true; + } + /// Merges the current [`Shell`] with another one by applying the given /// function to the messages of the latter. /// @@ -50,5 +59,14 @@ impl<'a, Message> Shell<'a, Message> { self.is_layout_invalid = self.is_layout_invalid || other.is_layout_invalid; + + self.are_widgets_invalid = + self.are_widgets_invalid || other.are_widgets_invalid; + } + + /// Returns whether the widgets of the current application have been + /// invalidated. + pub fn are_widgets_invalid(&self) -> bool { + self.are_widgets_invalid } } diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 40f7a204..1c78b754 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -42,7 +42,8 @@ where /// is naive way to set up our application loop: /// /// ```no_run - /// use iced_native::{UserInterface, Cache, Size}; + /// use iced_native::Size; + /// use iced_native::user_interface::{self, UserInterface}; /// use iced_wgpu::Renderer; /// /// # mod iced_wgpu { @@ -61,7 +62,7 @@ where /// # } /// // Initialization /// let mut counter = Counter::new(); - /// let mut cache = Cache::new(); + /// let mut cache = user_interface::Cache::new(); /// let mut renderer = Renderer::new(); /// let mut window_size = Size::new(1024.0, 768.0); /// @@ -136,7 +137,8 @@ where /// completing [the previous example](#example): /// /// ```no_run - /// use iced_native::{clipboard, UserInterface, Cache, Size, Point}; + /// use iced_native::{clipboard, Size, Point}; + /// use iced_native::user_interface::{self, UserInterface}; /// use iced_wgpu::Renderer; /// /// # mod iced_wgpu { @@ -155,7 +157,7 @@ where /// # pub fn update(&mut self, message: ()) {} /// # } /// let mut counter = Counter::new(); - /// let mut cache = Cache::new(); + /// let mut cache = user_interface::Cache::new(); /// let mut renderer = Renderer::new(); /// let mut window_size = Size::new(1024.0, 768.0); /// let mut cursor_position = Point::default(); @@ -176,7 +178,7 @@ where /// ); /// /// // Update the user interface - /// let event_statuses = user_interface.update( + /// let (state, event_statuses) = user_interface.update( /// &events, /// cursor_position, /// &mut renderer, @@ -199,7 +201,9 @@ where renderer: &mut Renderer, clipboard: &mut dyn Clipboard, messages: &mut Vec<Message>, - ) -> Vec<event::Status> { + ) -> (State, Vec<event::Status>) { + let mut state = State::Updated; + let (base_cursor, overlay_statuses) = if let Some(mut overlay) = self.root.overlay(Layout::new(&self.base.layout)) { @@ -227,7 +231,7 @@ where &mut shell, ); - shell.with_invalid_layout(|| { + shell.revalidate_layout(|| { layer = Self::overlay_layer( None, bounds, @@ -236,6 +240,10 @@ where ); }); + if shell.are_widgets_invalid() { + state = State::Outdated; + } + event_status }) .collect(); @@ -255,7 +263,7 @@ where (cursor_position, vec![event::Status::Ignored; events.len()]) }; - events + let event_statuses = events .iter() .cloned() .zip(overlay_statuses.into_iter()) @@ -271,7 +279,7 @@ where &mut shell, ); - shell.with_invalid_layout(|| { + shell.revalidate_layout(|| { let hash = { let hasher = &mut crate::Hasher::default(); self.root.hash_layout(hasher); @@ -288,9 +296,15 @@ where self.overlay = None; }); + if shell.are_widgets_invalid() { + state = State::Outdated; + } + event_status.merge(overlay_status) }) - .collect() + .collect(); + + (state, event_statuses) } /// Draws the [`UserInterface`] with the provided [`Renderer`]. @@ -306,7 +320,8 @@ where /// [completing the last example](#example-1): /// /// ```no_run - /// use iced_native::{clipboard, UserInterface, Cache, Size, Point}; + /// use iced_native::{clipboard, Size, Point}; + /// use iced_native::user_interface::{self, UserInterface}; /// use iced_wgpu::Renderer; /// /// # mod iced_wgpu { @@ -325,7 +340,7 @@ where /// # pub fn update(&mut self, message: ()) {} /// # } /// let mut counter = Counter::new(); - /// let mut cache = Cache::new(); + /// let mut cache = user_interface::Cache::new(); /// let mut renderer = Renderer::new(); /// let mut window_size = Size::new(1024.0, 768.0); /// let mut cursor_position = Point::default(); @@ -548,3 +563,9 @@ impl Default for Cache { Cache::new() } } + +#[derive(Debug, Clone, Copy)] +pub enum State { + Outdated, + Updated, +} diff --git a/native/src/widget/responsive.rs b/native/src/widget/responsive.rs index 0cb85d45..becaa980 100644 --- a/native/src/widget/responsive.rs +++ b/native/src/widget/responsive.rs @@ -80,6 +80,10 @@ where let Internal { content, state } = internal.deref_mut(); + if state.last_size != Some(state.last_layout.size()) { + shell.invalidate_widgets(); + } + let content = content.resolve(state, renderer); let content_layout = Layout::with_offset( |