summaryrefslogtreecommitdiff
path: root/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs
blob: c44ddd8fc3d10135b3d4122ab0ad76b087b00fc3 (plain)
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
                }
            }
        }
    }
}