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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
pub mod focusable;
pub mod scrollable;
pub mod text_input;
pub use focusable::Focusable;
pub use scrollable::Scrollable;
pub use text_input::TextInput;
use crate::widget::Id;
use std::fmt;
pub trait Operation<T> {
fn container(
&mut self,
id: Option<&Id>,
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
);
fn focusable(&mut self, _state: &mut dyn Focusable, _id: Option<&Id>) {}
fn scrollable(&mut self, _state: &mut dyn Scrollable, _id: Option<&Id>) {}
fn text_input(&mut self, _state: &mut dyn TextInput, _id: Option<&Id>) {}
fn finish(&self) -> Outcome<T> {
Outcome::None
}
}
pub enum Outcome<T> {
None,
Some(T),
Chain(Box<dyn Operation<T>>),
}
impl<T> fmt::Debug for Outcome<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::None => write!(f, "Outcome::None"),
Self::Some(output) => write!(f, "Outcome::Some({:?})", output),
Self::Chain(_) => write!(f, "Outcome::Chain(...)"),
}
}
}
pub fn scoped<T: 'static>(
target: Id,
operation: impl Operation<T> + 'static,
) -> impl Operation<T> {
struct ScopedOperation<Message> {
target: Id,
operation: Box<dyn Operation<Message>>,
}
impl<Message: 'static> Operation<Message> for ScopedOperation<Message> {
fn container(
&mut self,
id: Option<&Id>,
operate_on_children: &mut dyn FnMut(&mut dyn Operation<Message>),
) {
if id == Some(&self.target) {
operate_on_children(self.operation.as_mut());
} else {
operate_on_children(self);
}
}
fn finish(&self) -> Outcome<Message> {
match self.operation.finish() {
Outcome::Chain(next) => {
Outcome::Chain(Box::new(ScopedOperation {
target: self.target.clone(),
operation: next,
}))
}
outcome => outcome,
}
}
}
ScopedOperation {
target,
operation: Box::new(operation),
}
}