summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--glutin/src/application.rs14
-rw-r--r--lazy/src/component.rs4
-rw-r--r--native/src/lib.rs4
-rw-r--r--native/src/program/state.rs12
-rw-r--r--native/src/shell.rs20
-rw-r--r--native/src/user_interface.rs45
-rw-r--r--native/src/widget/responsive.rs4
-rw-r--r--winit/src/application.rs15
8 files changed, 85 insertions, 33 deletions
diff --git a/glutin/src/application.rs b/glutin/src/application.rs
index a1165de3..437c17ee 100644
--- a/glutin/src/application.rs
+++ b/glutin/src/application.rs
@@ -9,7 +9,8 @@ use iced_winit::application;
use iced_winit::conversion;
use iced_winit::futures;
use iced_winit::futures::channel::mpsc;
-use iced_winit::{Cache, Clipboard, Debug, Proxy, Settings};
+use iced_winit::user_interface;
+use iced_winit::{Clipboard, Debug, Proxy, Settings};
use glutin::window::Window;
use std::mem::ManuallyDrop;
@@ -177,7 +178,7 @@ async fn run_instance<A, E, C>(
let mut user_interface =
ManuallyDrop::new(application::build_user_interface(
&mut application,
- Cache::default(),
+ user_interface::Cache::default(),
&mut renderer,
state.logical_size(),
&mut debug,
@@ -198,7 +199,7 @@ async fn run_instance<A, E, C>(
debug.event_processing_started();
- let statuses = user_interface.update(
+ let (interface_state, statuses) = user_interface.update(
&events,
state.cursor_position(),
&mut renderer,
@@ -212,7 +213,12 @@ async fn run_instance<A, E, C>(
runtime.broadcast(event);
}
- if !messages.is_empty() {
+ if !messages.is_empty()
+ || matches!(
+ interface_state,
+ user_interface::State::Outdated
+ )
+ {
let cache =
ManuallyDrop::into_inner(user_interface).into_cache();
diff --git a/lazy/src/component.rs b/lazy/src/component.rs
index fd3f6ff7..48ee1d87 100644
--- a/lazy/src/component.rs
+++ b/lazy/src/component.rs
@@ -149,7 +149,7 @@ where
)
});
- local_shell.with_invalid_layout(|| shell.invalidate_layout());
+ local_shell.revalidate_layout(|| shell.invalidate_layout());
if !local_messages.is_empty() {
let mut component = self
@@ -375,7 +375,7 @@ where
})
.unwrap_or_else(|| iced_native::event::Status::Ignored);
- local_shell.with_invalid_layout(|| shell.invalidate_layout());
+ local_shell.revalidate_layout(|| shell.invalidate_layout());
if !local_messages.is_empty() {
let mut component =
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(
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 32423e80..e9212b5e 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -15,7 +15,7 @@ use iced_futures::futures;
use iced_futures::futures::channel::mpsc;
use iced_graphics::window;
use iced_native::program::Program;
-use iced_native::{Cache, UserInterface};
+use iced_native::user_interface::{self, UserInterface};
use std::mem::ManuallyDrop;
@@ -250,7 +250,7 @@ async fn run_instance<A, E, C>(
let mut user_interface = ManuallyDrop::new(build_user_interface(
&mut application,
- Cache::default(),
+ user_interface::Cache::default(),
&mut renderer,
state.logical_size(),
&mut debug,
@@ -271,7 +271,7 @@ async fn run_instance<A, E, C>(
debug.event_processing_started();
- let statuses = user_interface.update(
+ let (interface_state, statuses) = user_interface.update(
&events,
state.cursor_position(),
&mut renderer,
@@ -285,7 +285,12 @@ async fn run_instance<A, E, C>(
runtime.broadcast(event);
}
- if !messages.is_empty() {
+ if !messages.is_empty()
+ || matches!(
+ interface_state,
+ user_interface::State::Outdated,
+ )
+ {
let cache =
ManuallyDrop::into_inner(user_interface).into_cache();
@@ -471,7 +476,7 @@ pub fn requests_exit(
/// [`struct@Debug`] information accordingly.
pub fn build_user_interface<'a, A: Application>(
application: &'a mut A,
- cache: Cache,
+ cache: user_interface::Cache,
renderer: &mut A::Renderer,
size: Size,
debug: &mut Debug,