1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
use iced::advanced::widget::operation::{Outcome, Scrollable};
use iced::advanced::widget::{Id, Operation};
use iced::{Rectangle, Vector};
/// Produces an [`Operation`] that will find the drop zones that pass a filter on the zone's bounds.
/// For any drop zone to be considered, the Element must have some Id.
/// If `options` is `None`, all drop zones will be considered.
/// Depth determines how how deep into nested drop zones to go.
/// If 'depth' is `None`, nested dropzones will be fully explored
pub fn find_zones<F>(
filter: F,
options: Option<Vec<Id>>,
depth: Option<usize>,
) -> impl Operation<Vec<(Id, Rectangle)>>
where
F: Fn(&Rectangle) -> bool + Send + 'static,
{
struct FindDropZone<F> {
filter: F,
options: Option<Vec<Id>>,
zones: Vec<(Id, Rectangle)>,
max_depth: Option<usize>,
c_depth: usize,
offset: Vector,
}
impl<F> Operation<Vec<(Id, Rectangle)>> for FindDropZone<F>
where
F: Fn(&Rectangle) -> bool + Send + 'static,
{
fn container(
&mut self,
id: Option<&Id>,
bounds: iced::Rectangle,
operate_on_children: &mut dyn FnMut(
&mut dyn Operation<Vec<(Id, Rectangle)>>,
),
) {
match id {
Some(id) => {
let is_option = match &self.options {
Some(options) => options.contains(id),
None => true,
};
let bounds = bounds - self.offset;
if is_option && (self.filter)(&bounds) {
self.c_depth += 1;
self.zones.push((id.clone(), bounds));
}
}
None => (),
}
let goto_next = match &self.max_depth {
Some(m_depth) => self.c_depth < *m_depth,
None => true,
};
if goto_next {
operate_on_children(self);
}
}
fn finish(&self) -> Outcome<Vec<(Id, Rectangle)>> {
Outcome::Some(self.zones.clone())
}
fn scrollable(
&mut self,
_id: Option<&Id>,
bounds: Rectangle,
_content_bounds: Rectangle,
translation: Vector,
_state: &mut dyn Scrollable,
) {
if (self.filter)(&bounds) {
self.offset = self.offset + translation;
}
}
}
FindDropZone {
filter,
options,
zones: vec![],
max_depth: depth,
c_depth: 0,
offset: Vector { x: 0.0, y: 0.0 },
}
}
|