Introduce visible_bounds operation for Container
This commit is contained in:
parent
e29754f32d
commit
e2ba7ece83
16 changed files with 201 additions and 25 deletions
|
|
@ -5,7 +5,9 @@ use crate::overlay;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
use crate::widget;
|
use crate::widget;
|
||||||
use crate::widget::tree::{self, Tree};
|
use crate::widget::tree::{self, Tree};
|
||||||
use crate::{Clipboard, Color, Layout, Length, Rectangle, Shell, Widget};
|
use crate::{
|
||||||
|
Clipboard, Color, Layout, Length, Rectangle, Shell, Vector, Widget,
|
||||||
|
};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
|
@ -325,11 +327,12 @@ where
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&widget::Id>,
|
id: Option<&widget::Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(
|
operate_on_children: &mut dyn FnMut(
|
||||||
&mut dyn widget::Operation<T>,
|
&mut dyn widget::Operation<T>,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
self.operation.container(id, &mut |operation| {
|
self.operation.container(id, bounds, &mut |operation| {
|
||||||
operate_on_children(&mut MapOperation { operation });
|
operate_on_children(&mut MapOperation { operation });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -346,8 +349,10 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut dyn widget::operation::Scrollable,
|
state: &mut dyn widget::operation::Scrollable,
|
||||||
id: Option<&widget::Id>,
|
id: Option<&widget::Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
|
translation: Vector,
|
||||||
) {
|
) {
|
||||||
self.operation.scrollable(state, id);
|
self.operation.scrollable(state, id, bounds, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_input(
|
fn text_input(
|
||||||
|
|
|
||||||
|
|
@ -172,11 +172,12 @@ where
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&widget::Id>,
|
id: Option<&widget::Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(
|
operate_on_children: &mut dyn FnMut(
|
||||||
&mut dyn widget::Operation<T>,
|
&mut dyn widget::Operation<T>,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
self.operation.container(id, &mut |operation| {
|
self.operation.container(id, bounds, &mut |operation| {
|
||||||
operate_on_children(&mut MapOperation { operation });
|
operate_on_children(&mut MapOperation { operation });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -193,8 +194,10 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut dyn widget::operation::Scrollable,
|
state: &mut dyn widget::operation::Scrollable,
|
||||||
id: Option<&widget::Id>,
|
id: Option<&widget::Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
|
translation: Vector,
|
||||||
) {
|
) {
|
||||||
self.operation.scrollable(state, id);
|
self.operation.scrollable(state, id, bounds, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_input(
|
fn text_input(
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ where
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn widget::Operation<Message>,
|
operation: &mut dyn widget::Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.children.iter_mut().zip(layout.children()).for_each(
|
self.children.iter_mut().zip(layout.children()).for_each(
|
||||||
|(child, layout)| {
|
|(child, layout)| {
|
||||||
child.operate(layout, renderer, operation);
|
child.operate(layout, renderer, operation);
|
||||||
|
|
|
||||||
|
|
@ -197,3 +197,18 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Sub<Vector<T>> for Rectangle<T>
|
||||||
|
where
|
||||||
|
T: std::ops::Sub<Output = T>,
|
||||||
|
{
|
||||||
|
type Output = Rectangle<T>;
|
||||||
|
|
||||||
|
fn sub(self, translation: Vector<T>) -> Self {
|
||||||
|
Rectangle {
|
||||||
|
x: self.x - translation.x,
|
||||||
|
y: self.y - translation.y,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ pub use scrollable::Scrollable;
|
||||||
pub use text_input::TextInput;
|
pub use text_input::TextInput;
|
||||||
|
|
||||||
use crate::widget::Id;
|
use crate::widget::Id;
|
||||||
|
use crate::{Rectangle, Vector};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
@ -23,6 +24,7 @@ pub trait Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&Id>,
|
id: Option<&Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -30,7 +32,14 @@ pub trait Operation<T> {
|
||||||
fn focusable(&mut self, _state: &mut dyn Focusable, _id: Option<&Id>) {}
|
fn focusable(&mut self, _state: &mut dyn Focusable, _id: Option<&Id>) {}
|
||||||
|
|
||||||
/// Operates on a widget that can be scrolled.
|
/// Operates on a widget that can be scrolled.
|
||||||
fn scrollable(&mut self, _state: &mut dyn Scrollable, _id: Option<&Id>) {}
|
fn scrollable(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut dyn Scrollable,
|
||||||
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
|
_translation: Vector,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/// Operates on a widget that has text input.
|
/// Operates on a widget that has text input.
|
||||||
fn text_input(&mut self, _state: &mut dyn TextInput, _id: Option<&Id>) {}
|
fn text_input(&mut self, _state: &mut dyn TextInput, _id: Option<&Id>) {}
|
||||||
|
|
@ -92,6 +101,7 @@ where
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&Id>,
|
id: Option<&Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
|
||||||
) {
|
) {
|
||||||
struct MapRef<'a, A> {
|
struct MapRef<'a, A> {
|
||||||
|
|
@ -102,11 +112,12 @@ where
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&Id>,
|
id: Option<&Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
|
||||||
) {
|
) {
|
||||||
let Self { operation, .. } = self;
|
let Self { operation, .. } = self;
|
||||||
|
|
||||||
operation.container(id, &mut |operation| {
|
operation.container(id, bounds, &mut |operation| {
|
||||||
operate_on_children(&mut MapRef { operation });
|
operate_on_children(&mut MapRef { operation });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -115,8 +126,10 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut dyn Scrollable,
|
state: &mut dyn Scrollable,
|
||||||
id: Option<&Id>,
|
id: Option<&Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
|
translation: Vector,
|
||||||
) {
|
) {
|
||||||
self.operation.scrollable(state, id);
|
self.operation.scrollable(state, id, bounds, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focusable(
|
fn focusable(
|
||||||
|
|
@ -145,15 +158,21 @@ where
|
||||||
MapRef {
|
MapRef {
|
||||||
operation: operation.as_mut(),
|
operation: operation.as_mut(),
|
||||||
}
|
}
|
||||||
.container(id, operate_on_children);
|
.container(id, bounds, operate_on_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focusable(&mut self, state: &mut dyn Focusable, id: Option<&Id>) {
|
fn focusable(&mut self, state: &mut dyn Focusable, id: Option<&Id>) {
|
||||||
self.operation.focusable(state, id);
|
self.operation.focusable(state, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollable(&mut self, state: &mut dyn Scrollable, id: Option<&Id>) {
|
fn scrollable(
|
||||||
self.operation.scrollable(state, id);
|
&mut self,
|
||||||
|
state: &mut dyn Scrollable,
|
||||||
|
id: Option<&Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
|
translation: Vector,
|
||||||
|
) {
|
||||||
|
self.operation.scrollable(state, id, bounds, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) {
|
fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) {
|
||||||
|
|
@ -197,6 +216,7 @@ pub fn scope<T: 'static>(
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&Id>,
|
id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<Message>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<Message>),
|
||||||
) {
|
) {
|
||||||
if id == Some(&self.target) {
|
if id == Some(&self.target) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! Operate on widgets that can be focused.
|
//! Operate on widgets that can be focused.
|
||||||
use crate::widget::operation::{Operation, Outcome};
|
use crate::widget::operation::{Operation, Outcome};
|
||||||
use crate::widget::Id;
|
use crate::widget::Id;
|
||||||
|
use crate::Rectangle;
|
||||||
|
|
||||||
/// The internal state of a widget that can be focused.
|
/// The internal state of a widget that can be focused.
|
||||||
pub trait Focusable {
|
pub trait Focusable {
|
||||||
|
|
@ -45,6 +46,7 @@ pub fn focus<T>(target: Id) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -80,6 +82,7 @@ where
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -126,6 +129,7 @@ pub fn focus_previous<T>() -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -159,6 +163,7 @@ pub fn focus_next<T>() -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -185,6 +190,7 @@ pub fn find_focused() -> impl Operation<Id> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<Id>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<Id>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
//! Operate on widgets that can be scrolled.
|
//! Operate on widgets that can be scrolled.
|
||||||
use crate::widget::{Id, Operation};
|
use crate::widget::{Id, Operation};
|
||||||
|
use crate::{Rectangle, Vector};
|
||||||
|
|
||||||
/// The internal state of a widget that can be scrolled.
|
/// The internal state of a widget that can be scrolled.
|
||||||
pub trait Scrollable {
|
pub trait Scrollable {
|
||||||
|
|
@ -22,12 +23,19 @@ pub fn snap_to<T>(target: Id, offset: RelativeOffset) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollable(&mut self, state: &mut dyn Scrollable, id: Option<&Id>) {
|
fn scrollable(
|
||||||
|
&mut self,
|
||||||
|
state: &mut dyn Scrollable,
|
||||||
|
id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
|
_translation: Vector,
|
||||||
|
) {
|
||||||
if Some(&self.target) == id {
|
if Some(&self.target) == id {
|
||||||
state.snap_to(self.offset);
|
state.snap_to(self.offset);
|
||||||
}
|
}
|
||||||
|
|
@ -49,12 +57,19 @@ pub fn scroll_to<T>(target: Id, offset: AbsoluteOffset) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollable(&mut self, state: &mut dyn Scrollable, id: Option<&Id>) {
|
fn scrollable(
|
||||||
|
&mut self,
|
||||||
|
state: &mut dyn Scrollable,
|
||||||
|
id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
|
_translation: Vector,
|
||||||
|
) {
|
||||||
if Some(&self.target) == id {
|
if Some(&self.target) == id {
|
||||||
state.scroll_to(self.offset);
|
state.scroll_to(self.offset);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! Operate on widgets that have text input.
|
//! Operate on widgets that have text input.
|
||||||
use crate::widget::operation::Operation;
|
use crate::widget::operation::Operation;
|
||||||
use crate::widget::Id;
|
use crate::widget::Id;
|
||||||
|
use crate::Rectangle;
|
||||||
|
|
||||||
/// The internal state of a widget that has text input.
|
/// The internal state of a widget that has text input.
|
||||||
pub trait TextInput {
|
pub trait TextInput {
|
||||||
|
|
@ -34,6 +35,7 @@ pub fn move_cursor_to_front<T>(target: Id) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -63,6 +65,7 @@ pub fn move_cursor_to_end<T>(target: Id) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -93,6 +96,7 @@ pub fn move_cursor_to<T>(target: Id, position: usize) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
@ -121,6 +125,7 @@ pub fn select_all<T>(target: Id) -> impl Operation<T> {
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: Option<&Id>,
|
_id: Option<&Id>,
|
||||||
|
_bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||||
) {
|
) {
|
||||||
operate_on_children(self)
|
operate_on_children(self)
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ mod toast {
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn Operation<Message>,
|
operation: &mut dyn Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.content.as_widget().operate(
|
self.content.as_widget().operate(
|
||||||
&mut state.children[0],
|
&mut state.children[0],
|
||||||
layout,
|
layout,
|
||||||
|
|
@ -622,7 +622,7 @@ mod toast {
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn widget::Operation<Message>,
|
operation: &mut dyn widget::Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.toasts
|
self.toasts
|
||||||
.iter()
|
.iter()
|
||||||
.zip(self.state.iter_mut())
|
.zip(self.state.iter_mut())
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ where
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn Operation<Message>,
|
operation: &mut dyn Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.content.as_widget().operate(
|
self.content.as_widget().operate(
|
||||||
&mut tree.children[0],
|
&mut tree.children[0],
|
||||||
layout.children().next().unwrap(),
|
layout.children().next().unwrap(),
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ where
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn Operation<Message>,
|
operation: &mut dyn Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.children
|
self.children
|
||||||
.iter()
|
.iter()
|
||||||
.zip(&mut tree.children)
|
.zip(&mut tree.children)
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,9 @@ use crate::core::renderer;
|
||||||
use crate::core::widget::{self, Operation, Tree};
|
use crate::core::widget::{self, Operation, Tree};
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Background, Clipboard, Color, Element, Layout, Length, Padding, Pixels,
|
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};
|
pub use iced_style::container::{Appearance, StyleSheet};
|
||||||
|
|
||||||
|
|
@ -180,6 +181,7 @@ where
|
||||||
) {
|
) {
|
||||||
operation.container(
|
operation.container(
|
||||||
self.id.as_ref().map(|id| &id.0),
|
self.id.as_ref().map(|id| &id.0),
|
||||||
|
layout.bounds(),
|
||||||
&mut |operation| {
|
&mut |operation| {
|
||||||
self.content.as_widget().operate(
|
self.content.as_widget().operate(
|
||||||
&mut tree.children[0],
|
&mut tree.children[0],
|
||||||
|
|
@ -368,3 +370,92 @@ impl From<Id> for widget::Id {
|
||||||
id.0
|
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;
|
||||||
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::runtime::overlay::Nested;
|
use crate::runtime::overlay::Nested;
|
||||||
|
|
||||||
|
|
@ -340,11 +341,12 @@ where
|
||||||
fn container(
|
fn container(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Option<&widget::Id>,
|
id: Option<&widget::Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
operate_on_children: &mut dyn FnMut(
|
operate_on_children: &mut dyn FnMut(
|
||||||
&mut dyn widget::Operation<T>,
|
&mut dyn widget::Operation<T>,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
self.operation.container(id, &mut |operation| {
|
self.operation.container(id, bounds, &mut |operation| {
|
||||||
operate_on_children(&mut MapOperation { operation });
|
operate_on_children(&mut MapOperation { operation });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -369,8 +371,10 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut dyn widget::operation::Scrollable,
|
state: &mut dyn widget::operation::Scrollable,
|
||||||
id: Option<&widget::Id>,
|
id: Option<&widget::Id>,
|
||||||
|
bounds: Rectangle,
|
||||||
|
translation: Vector,
|
||||||
) {
|
) {
|
||||||
self.operation.scrollable(state, id);
|
self.operation.scrollable(state, id, bounds, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn custom(
|
fn custom(
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ where
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn widget::Operation<Message>,
|
operation: &mut dyn widget::Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.contents
|
self.contents
|
||||||
.iter()
|
.iter()
|
||||||
.zip(&mut tree.children)
|
.zip(&mut tree.children)
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ where
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
operation: &mut dyn Operation<Message>,
|
operation: &mut dyn Operation<Message>,
|
||||||
) {
|
) {
|
||||||
operation.container(None, &mut |operation| {
|
operation.container(None, layout.bounds(), &mut |operation| {
|
||||||
self.children
|
self.children
|
||||||
.iter()
|
.iter()
|
||||||
.zip(&mut tree.children)
|
.zip(&mut tree.children)
|
||||||
|
|
|
||||||
|
|
@ -254,10 +254,22 @@ where
|
||||||
) {
|
) {
|
||||||
let state = tree.state.downcast_mut::<State>();
|
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(
|
operation.container(
|
||||||
self.id.as_ref().map(|id| &id.0),
|
self.id.as_ref().map(|id| &id.0),
|
||||||
|
bounds,
|
||||||
&mut |operation| {
|
&mut |operation| {
|
||||||
self.content.as_widget().operate(
|
self.content.as_widget().operate(
|
||||||
&mut tree.children[0],
|
&mut tree.children[0],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue