Introduce visible_bounds operation for Container
This commit is contained in:
parent
e29754f32d
commit
e2ba7ece83
16 changed files with 201 additions and 25 deletions
|
|
@ -181,7 +181,7 @@ where
|
|||
renderer: &Renderer,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
operation.container(None, layout.bounds(), &mut |operation| {
|
||||
self.content.as_widget().operate(
|
||||
&mut tree.children[0],
|
||||
layout.children().next().unwrap(),
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ where
|
|||
renderer: &Renderer,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
operation.container(None, layout.bounds(), &mut |operation| {
|
||||
self.children
|
||||
.iter()
|
||||
.zip(&mut tree.children)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ use crate::core::renderer;
|
|||
use crate::core::widget::{self, Operation, Tree};
|
||||
use crate::core::{
|
||||
Background, Clipboard, Color, Element, Layout, Length, Padding, Pixels,
|
||||
Point, Rectangle, Shell, Widget,
|
||||
Point, Rectangle, Shell, Size, Vector, Widget,
|
||||
};
|
||||
use crate::runtime::Command;
|
||||
|
||||
pub use iced_style::container::{Appearance, StyleSheet};
|
||||
|
||||
|
|
@ -180,6 +181,7 @@ where
|
|||
) {
|
||||
operation.container(
|
||||
self.id.as_ref().map(|id| &id.0),
|
||||
layout.bounds(),
|
||||
&mut |operation| {
|
||||
self.content.as_widget().operate(
|
||||
&mut tree.children[0],
|
||||
|
|
@ -368,3 +370,92 @@ impl From<Id> for widget::Id {
|
|||
id.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces a [`Command`] that queries the visible screen bounds of the
|
||||
/// [`Container`] with the given [`Id`].
|
||||
pub fn visible_bounds(id: Id) -> Command<Option<Rectangle>> {
|
||||
struct VisibleBounds {
|
||||
target: widget::Id,
|
||||
depth: usize,
|
||||
scrollables: Vec<(Vector, Rectangle, usize)>,
|
||||
bounds: Option<Rectangle>,
|
||||
}
|
||||
|
||||
impl Operation<Option<Rectangle>> for VisibleBounds {
|
||||
fn scrollable(
|
||||
&mut self,
|
||||
_state: &mut dyn widget::operation::Scrollable,
|
||||
_id: Option<&widget::Id>,
|
||||
bounds: Rectangle,
|
||||
translation: Vector,
|
||||
) {
|
||||
match self.scrollables.last() {
|
||||
Some((last_translation, last_viewport, _depth)) => {
|
||||
let viewport = last_viewport
|
||||
.intersection(&(bounds - *last_translation))
|
||||
.unwrap_or(Rectangle::new(Point::ORIGIN, Size::ZERO));
|
||||
|
||||
self.scrollables.push((
|
||||
translation + *last_translation,
|
||||
viewport,
|
||||
self.depth,
|
||||
));
|
||||
}
|
||||
None => {
|
||||
self.scrollables.push((translation, bounds, self.depth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn container(
|
||||
&mut self,
|
||||
id: Option<&widget::Id>,
|
||||
bounds: Rectangle,
|
||||
operate_on_children: &mut dyn FnMut(
|
||||
&mut dyn Operation<Option<Rectangle>>,
|
||||
),
|
||||
) {
|
||||
if self.bounds.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
if id == Some(&self.target) {
|
||||
match self.scrollables.last() {
|
||||
Some((translation, viewport, _)) => {
|
||||
self.bounds =
|
||||
viewport.intersection(&(bounds - *translation));
|
||||
}
|
||||
None => {
|
||||
self.bounds = Some(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self.depth += 1;
|
||||
|
||||
operate_on_children(self);
|
||||
|
||||
self.depth -= 1;
|
||||
|
||||
match self.scrollables.last() {
|
||||
Some((_, _, depth)) if self.depth == *depth => {
|
||||
let _ = self.scrollables.pop();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&self) -> widget::operation::Outcome<Option<Rectangle>> {
|
||||
widget::operation::Outcome::Some(self.bounds)
|
||||
}
|
||||
}
|
||||
|
||||
Command::widget(VisibleBounds {
|
||||
target: id.into(),
|
||||
depth: 0,
|
||||
scrollables: Vec::new(),
|
||||
bounds: None,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use crate::core::renderer;
|
|||
use crate::core::widget;
|
||||
use crate::core::widget::tree::{self, Tree};
|
||||
use crate::core::{
|
||||
self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget,
|
||||
self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Vector,
|
||||
Widget,
|
||||
};
|
||||
use crate::runtime::overlay::Nested;
|
||||
|
||||
|
|
@ -340,11 +341,12 @@ where
|
|||
fn container(
|
||||
&mut self,
|
||||
id: Option<&widget::Id>,
|
||||
bounds: Rectangle,
|
||||
operate_on_children: &mut dyn FnMut(
|
||||
&mut dyn widget::Operation<T>,
|
||||
),
|
||||
) {
|
||||
self.operation.container(id, &mut |operation| {
|
||||
self.operation.container(id, bounds, &mut |operation| {
|
||||
operate_on_children(&mut MapOperation { operation });
|
||||
});
|
||||
}
|
||||
|
|
@ -369,8 +371,10 @@ where
|
|||
&mut self,
|
||||
state: &mut dyn widget::operation::Scrollable,
|
||||
id: Option<&widget::Id>,
|
||||
bounds: Rectangle,
|
||||
translation: Vector,
|
||||
) {
|
||||
self.operation.scrollable(state, id);
|
||||
self.operation.scrollable(state, id, bounds, translation);
|
||||
}
|
||||
|
||||
fn custom(
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ where
|
|||
renderer: &Renderer,
|
||||
operation: &mut dyn widget::Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
operation.container(None, layout.bounds(), &mut |operation| {
|
||||
self.contents
|
||||
.iter()
|
||||
.zip(&mut tree.children)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ where
|
|||
renderer: &Renderer,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
operation.container(None, layout.bounds(), &mut |operation| {
|
||||
self.children
|
||||
.iter()
|
||||
.zip(&mut tree.children)
|
||||
|
|
|
|||
|
|
@ -254,10 +254,22 @@ where
|
|||
) {
|
||||
let state = tree.state.downcast_mut::<State>();
|
||||
|
||||
operation.scrollable(state, self.id.as_ref().map(|id| &id.0));
|
||||
let bounds = layout.bounds();
|
||||
let content_layout = layout.children().next().unwrap();
|
||||
let content_bounds = content_layout.bounds();
|
||||
let translation =
|
||||
state.translation(self.direction, bounds, content_bounds);
|
||||
|
||||
operation.scrollable(
|
||||
state,
|
||||
self.id.as_ref().map(|id| &id.0),
|
||||
bounds,
|
||||
translation,
|
||||
);
|
||||
|
||||
operation.container(
|
||||
self.id.as_ref().map(|id| &id.0),
|
||||
bounds,
|
||||
&mut |operation| {
|
||||
self.content.as_widget().operate(
|
||||
&mut tree.children[0],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue