Merge pull request #2142 from iced-rs/fix/overlay-composition

Fix `Overlay` composition
This commit is contained in:
Héctor Ramón 2023-11-21 19:03:49 +01:00 committed by GitHub
commit 170db35891
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 68 additions and 28 deletions

View file

@ -11,7 +11,7 @@ use crate::mouse;
use crate::renderer; use crate::renderer;
use crate::widget; use crate::widget;
use crate::widget::Tree; use crate::widget::Tree;
use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size}; use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size, Vector};
/// An interactive component that can be displayed on top of other widgets. /// An interactive component that can be displayed on top of other widgets.
pub trait Overlay<Message, Renderer> pub trait Overlay<Message, Renderer>
@ -29,6 +29,7 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
translation: Vector,
) -> layout::Node; ) -> layout::Node;
/// Draws the [`Overlay`] using the associated `Renderer`. /// Draws the [`Overlay`] using the associated `Renderer`.

View file

@ -13,6 +13,7 @@ use std::any::Any;
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Element<'a, Message, Renderer> { pub struct Element<'a, Message, Renderer> {
position: Point, position: Point,
translation: Vector,
overlay: Box<dyn Overlay<Message, Renderer> + 'a>, overlay: Box<dyn Overlay<Message, Renderer> + 'a>,
} }
@ -25,7 +26,11 @@ where
position: Point, position: Point,
overlay: Box<dyn Overlay<Message, Renderer> + 'a>, overlay: Box<dyn Overlay<Message, Renderer> + 'a>,
) -> Self { ) -> Self {
Self { position, overlay } Self {
position,
overlay,
translation: Vector::ZERO,
}
} }
/// Returns the position of the [`Element`]. /// Returns the position of the [`Element`].
@ -36,6 +41,7 @@ where
/// Translates the [`Element`]. /// Translates the [`Element`].
pub fn translate(mut self, translation: Vector) -> Self { pub fn translate(mut self, translation: Vector) -> Self {
self.position = self.position + translation; self.position = self.position + translation;
self.translation = self.translation + translation;
self self
} }
@ -48,6 +54,7 @@ where
{ {
Element { Element {
position: self.position, position: self.position,
translation: self.translation,
overlay: Box::new(Map::new(self.overlay, f)), overlay: Box::new(Map::new(self.overlay, f)),
} }
} }
@ -59,8 +66,12 @@ where
bounds: Size, bounds: Size,
translation: Vector, translation: Vector,
) -> layout::Node { ) -> layout::Node {
self.overlay self.overlay.layout(
.layout(renderer, bounds, self.position + translation) renderer,
bounds,
self.position + translation,
self.translation + translation,
)
} }
/// Processes a runtime [`Event`]. /// Processes a runtime [`Event`].
@ -154,8 +165,9 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
translation: Vector,
) -> layout::Node { ) -> layout::Node {
self.content.layout(renderer, bounds, position) self.content.layout(renderer, bounds, position, translation)
} }
fn operate( fn operate(

View file

@ -4,7 +4,9 @@ use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::widget; use crate::widget;
use crate::{Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size}; use crate::{
Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size, Vector,
};
/// An [`Overlay`] container that displays multiple overlay [`overlay::Element`] /// An [`Overlay`] container that displays multiple overlay [`overlay::Element`]
/// children. /// children.
@ -64,10 +66,9 @@ where
&mut self, &mut self,
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, _position: Point,
translation: Vector,
) -> layout::Node { ) -> layout::Node {
let translation = position - Point::ORIGIN;
layout::Node::with_children( layout::Node::with_children(
bounds, bounds,
self.children self.children

View file

@ -231,6 +231,7 @@ mod modal {
use iced::mouse; use iced::mouse;
use iced::{ use iced::{
BorderRadius, Color, Element, Event, Length, Point, Rectangle, Size, BorderRadius, Color, Element, Event, Length, Point, Rectangle, Size,
Vector,
}; };
/// A widget that centers a modal element over some base element /// A widget that centers a modal element over some base element
@ -413,6 +414,7 @@ mod modal {
renderer: &Renderer, renderer: &Renderer,
_bounds: Size, _bounds: Size,
position: Point, position: Point,
_translation: Vector,
) -> layout::Node { ) -> layout::Node {
let limits = layout::Limits::new(Size::ZERO, self.size) let limits = layout::Limits::new(Size::ZERO, self.size)
.width(Length::Fill) .width(Length::Fill)

View file

@ -511,6 +511,7 @@ mod toast {
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
_translation: Vector,
) -> layout::Node { ) -> layout::Node {
let limits = layout::Limits::new(Size::ZERO, bounds) let limits = layout::Limits::new(Size::ZERO, bounds)
.width(Length::Fill) .width(Length::Fill)

View file

@ -4,7 +4,9 @@ use crate::core::mouse;
use crate::core::overlay; use crate::core::overlay;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget; use crate::core::widget;
use crate::core::{Clipboard, Event, Layout, Point, Rectangle, Shell, Size}; use crate::core::{
Clipboard, Event, Layout, Point, Rectangle, Shell, Size, Vector,
};
/// An overlay container that displays nested overlays /// An overlay container that displays nested overlays
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
@ -33,19 +35,18 @@ where
&mut self, &mut self,
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, _position: Point,
translation: Vector,
) -> layout::Node { ) -> layout::Node {
fn recurse<Message, Renderer>( fn recurse<Message, Renderer>(
element: &mut overlay::Element<'_, Message, Renderer>, element: &mut overlay::Element<'_, Message, Renderer>,
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, translation: Vector,
) -> layout::Node ) -> layout::Node
where where
Renderer: renderer::Renderer, Renderer: renderer::Renderer,
{ {
let translation = position - Point::ORIGIN;
let node = element.layout(renderer, bounds, translation); let node = element.layout(renderer, bounds, translation);
if let Some(mut nested) = if let Some(mut nested) =
@ -55,7 +56,7 @@ where
node.size(), node.size(),
vec![ vec![
node, node,
recurse(&mut nested, renderer, bounds, position), recurse(&mut nested, renderer, bounds, translation),
], ],
) )
} else { } else {
@ -63,7 +64,7 @@ where
} }
} }
recurse(&mut self.overlay, renderer, bounds, position) recurse(&mut self.overlay, renderer, bounds, translation)
} }
/// Draws the [`Nested`] overlay using the associated `Renderer`. /// Draws the [`Nested`] overlay using the associated `Renderer`.

View file

@ -5,7 +5,9 @@ use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget; use crate::core::widget;
use crate::core::window; use crate::core::window;
use crate::core::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size}; use crate::core::{
Clipboard, Element, Layout, Point, Rectangle, Shell, Size, Vector,
};
use crate::overlay; use crate::overlay;
/// A set of interactive graphical elements with a specific [`Layout`]. /// A set of interactive graphical elements with a specific [`Layout`].
@ -199,7 +201,8 @@ where
let bounds = self.bounds; let bounds = self.bounds;
let mut overlay = manual_overlay.as_mut().unwrap(); let mut overlay = manual_overlay.as_mut().unwrap();
let mut layout = overlay.layout(renderer, bounds, Point::ORIGIN); let mut layout =
overlay.layout(renderer, bounds, Point::ORIGIN, Vector::ZERO);
let mut event_statuses = Vec::new(); let mut event_statuses = Vec::new();
for event in events.iter().cloned() { for event in events.iter().cloned() {
@ -253,8 +256,12 @@ where
overlay = manual_overlay.as_mut().unwrap(); overlay = manual_overlay.as_mut().unwrap();
shell.revalidate_layout(|| { shell.revalidate_layout(|| {
layout = layout = overlay.layout(
overlay.layout(renderer, bounds, Point::ORIGIN); renderer,
bounds,
Point::ORIGIN,
Vector::ZERO,
);
}); });
} }
@ -448,7 +455,12 @@ where
.map(overlay::Nested::new) .map(overlay::Nested::new)
{ {
let overlay_layout = self.overlay.take().unwrap_or_else(|| { let overlay_layout = self.overlay.take().unwrap_or_else(|| {
overlay.layout(renderer, self.bounds, Point::ORIGIN) overlay.layout(
renderer,
self.bounds,
Point::ORIGIN,
Vector::ZERO,
)
}); });
let cursor = if cursor let cursor = if cursor
@ -566,8 +578,12 @@ where
.map(overlay::Nested::new) .map(overlay::Nested::new)
{ {
if self.overlay.is_none() { if self.overlay.is_none() {
self.overlay = self.overlay = Some(overlay.layout(
Some(overlay.layout(renderer, self.bounds, Point::ORIGIN)); renderer,
self.bounds,
Point::ORIGIN,
Vector::ZERO,
));
} }
overlay.operate( overlay.operate(

View file

@ -18,7 +18,7 @@ use crate::core::widget::tree::{self, Tree};
use crate::core::widget::{self, Widget}; use crate::core::widget::{self, Widget};
use crate::core::Element; use crate::core::Element;
use crate::core::{ use crate::core::{
self, Clipboard, Hasher, Length, Point, Rectangle, Shell, Size, self, Clipboard, Hasher, Length, Point, Rectangle, Shell, Size, Vector,
}; };
use crate::runtime::overlay::Nested; use crate::runtime::overlay::Nested;
@ -333,9 +333,10 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
translation: Vector,
) -> layout::Node { ) -> layout::Node {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
overlay.layout(renderer, bounds, position) overlay.layout(renderer, bounds, position, translation)
}) })
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -577,9 +577,10 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
translation: Vector,
) -> layout::Node { ) -> layout::Node {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
overlay.layout(renderer, bounds, position) overlay.layout(renderer, bounds, position, translation)
}) })
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -6,7 +6,8 @@ use crate::core::renderer;
use crate::core::widget; use crate::core::widget;
use crate::core::widget::tree::{self, Tree}; use crate::core::widget::tree::{self, Tree};
use crate::core::{ use crate::core::{
self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget, self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Vector,
Widget,
}; };
use crate::horizontal_space; use crate::horizontal_space;
use crate::runtime::overlay::Nested; use crate::runtime::overlay::Nested;
@ -367,9 +368,10 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
translation: Vector,
) -> layout::Node { ) -> layout::Node {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
overlay.layout(renderer, bounds, position) overlay.layout(renderer, bounds, position, translation)
}) })
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -236,6 +236,7 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
_translation: Vector,
) -> layout::Node { ) -> layout::Node {
let space_below = bounds.height - (position.y + self.target_height); let space_below = bounds.height - (position.y + self.target_height);
let space_above = position.y; let space_above = position.y;

View file

@ -325,6 +325,7 @@ where
renderer: &Renderer, renderer: &Renderer,
bounds: Size, bounds: Size,
position: Point, position: Point,
_translation: Vector,
) -> layout::Node { ) -> layout::Node {
let viewport = Rectangle::with_size(bounds); let viewport = Rectangle::with_size(bounds);