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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
use iced::Element;
use crate::traits::Component;
use super::{Action, Message, Navigation};
impl<'a, TOption> Component<'a, Message<TOption>, Action<TOption>> for Navigation<TOption>
where
TOption: Clone + PartialEq + 'a,
Element<'a, Message<TOption>>: From<&'a TOption>,
{
fn update(&mut self, message: Message<TOption>) -> Action<TOption> {
let navigation: &mut Navigation<TOption> = self;
match message {
Message::SelectOption(option) => {
if navigation
.active_option
.as_ref()
.is_some_and(|active_option| TOption::eq(active_option, &option))
{
Action::None
} else if let Some(index) = navigation
.options_before_active
.iter()
.position(|o| TOption::eq(o, &option))
{
let split = navigation.options_before_active.split_at(index);
navigation.options_after_active = vec![
navigation
.active_option
.clone()
.map_or(vec![], |active_option| vec![active_option]),
split.1.split_at(1).1.to_vec(),
navigation.options_after_active.clone(),
]
.concat();
navigation.options_before_active = split.0.to_vec();
navigation.active_option = Some(option.clone());
Action::SelectOption(option)
} else if let Some(index) = navigation
.options_after_active
.iter()
.position(|o| TOption::eq(o, &option))
{
let split = navigation.options_after_active.split_at(index);
navigation.options_before_active = vec![
navigation.options_before_active.clone(),
split.0.to_vec(),
navigation
.active_option
.clone()
.map_or(vec![], |active_option| vec![active_option]),
]
.concat();
navigation.active_option = Some(option.clone());
navigation.options_after_active = split.1.split_at(1).1.to_vec();
Action::SelectOption(option)
} else {
if let Some(active_option) = &navigation.active_option {
navigation.options_before_active.push(active_option.clone());
}
navigation
.options_before_active
.append(&mut navigation.options_after_active);
navigation.active_option = Some(option.clone());
navigation.options_after_active = vec![];
Action::SelectOption(option)
}
}
Message::SetOptions(options) => {
let active_option_index =
navigation
.active_option
.clone()
.map_or(Option::None, |active_option| {
options
.iter()
.position(|option| active_option == option.clone())
});
if let Some(active_option_index) = active_option_index {
let split = options.split_at(active_option_index);
navigation.options_before_active = split.0.to_vec();
navigation.options_after_active = split.1.split_at(1).1.to_vec();
Action::None
} else {
navigation.options_before_active = options
.split_last()
.map_or_else(Vec::new, |(_last, rest)| rest.to_vec());
navigation.active_option = options.last().cloned();
options
.last()
.cloned()
.map_or(Action::None, Action::SelectOption)
}
}
Message::SelectNext => {
if let Some(next) = navigation.options_after_active.clone().first() {
navigation.options_before_active = vec![
navigation.options_before_active.clone(),
navigation.active_option.clone().map_or(vec![], |o| vec![o]),
]
.concat();
navigation.active_option = Some(next.clone());
navigation.options_after_active =
navigation.options_after_active.split_at(1).1.to_vec();
Action::SelectOption(next.clone())
} else {
Action::None
}
}
Message::SelectPrev => {
if let Some(prev) = navigation.options_before_active.clone().last() {
navigation.options_after_active = vec![
navigation.active_option.clone().map_or(vec![], |o| vec![o]),
navigation.options_after_active.clone(),
]
.concat();
navigation.active_option = Some(prev.clone());
navigation.options_before_active = navigation
.options_before_active
.split_last()
.map(|split| split.1.to_vec())
.unwrap_or_else(Vec::new);
Action::SelectOption(prev.clone())
} else {
Action::None
}
}
}
}
}
|