diff options
Diffstat (limited to 'schist_desktop_gui/src')
4 files changed, 131 insertions, 81 deletions
diff --git a/schist_desktop_gui/src/gui/components/navigation.rs b/schist_desktop_gui/src/gui/components/navigation.rs index d1f7938..4dc762a 100644 --- a/schist_desktop_gui/src/gui/components/navigation.rs +++ b/schist_desktop_gui/src/gui/components/navigation.rs @@ -1,4 +1,6 @@ mod navigate_navigation; +mod navigation_select_option; +mod navigation_set_options; mod update_navigation; mod view_navigation; mod view_navigation_button; diff --git a/schist_desktop_gui/src/gui/components/navigation/navigation_select_option.rs b/schist_desktop_gui/src/gui/components/navigation/navigation_select_option.rs new file mode 100644 index 0000000..4192059 --- /dev/null +++ b/schist_desktop_gui/src/gui/components/navigation/navigation_select_option.rs @@ -0,0 +1,71 @@ +use iced::Element; + +use super::{Message, Navigation}; + +pub enum SelectOptionResult<TOption> { + AlreadySelected, + SelectedExistingOption(TOption), + SelectedNewOption(TOption), +} + +impl<'a, TOption> Navigation<TOption> +where + TOption: Clone + PartialEq + 'a, + Element<'a, Message<TOption>>: From<&'a TOption>, +{ + pub fn select_option(&mut self, option: TOption) -> SelectOptionResult<TOption> + where + TOption: Clone + PartialEq + 'a, + { + if self + .active_option + .as_ref() + .is_some_and(|active_option| TOption::eq(active_option, &option)) + { + SelectOptionResult::AlreadySelected + } else if let Some(index) = self + .options_before_active + .iter() + .position(|o| TOption::eq(o, &option)) + { + let split = self.options_before_active.split_at(index); + self.options_after_active = vec![ + self.active_option + .clone() + .map_or(vec![], |active_option| vec![active_option]), + split.1.split_at(1).1.to_vec(), + self.options_after_active.clone(), + ] + .concat(); + self.options_before_active = split.0.to_vec(); + self.active_option = Some(option.clone()); + SelectOptionResult::SelectedExistingOption(option) + } else if let Some(index) = self + .options_after_active + .iter() + .position(|o| TOption::eq(o, &option)) + { + let split = self.options_after_active.split_at(index); + self.options_before_active = vec![ + self.options_before_active.clone(), + split.0.to_vec(), + self.active_option + .clone() + .map_or(vec![], |active_option| vec![active_option]), + ] + .concat(); + self.active_option = Some(option.clone()); + self.options_after_active = split.1.split_at(1).1.to_vec(); + SelectOptionResult::SelectedExistingOption(option) + } else { + if let Some(active_option) = &self.active_option { + self.options_before_active.push(active_option.clone()); + } + self.options_before_active + .append(&mut self.options_after_active); + self.active_option = Some(option.clone()); + self.options_after_active = vec![]; + SelectOptionResult::SelectedNewOption(option) + } + } +} diff --git a/schist_desktop_gui/src/gui/components/navigation/navigation_set_options.rs b/schist_desktop_gui/src/gui/components/navigation/navigation_set_options.rs new file mode 100644 index 0000000..c2c9952 --- /dev/null +++ b/schist_desktop_gui/src/gui/components/navigation/navigation_set_options.rs @@ -0,0 +1,40 @@ +use iced::Element; + +use super::{Message, Navigation}; + +pub enum SetOptionsResult<TOption> { + SetOptionsAndKeptSelection, + SetOptionsAndSetSelectedOption(TOption), +} + +impl<'a, TOption> Navigation<TOption> +where + TOption: Clone + PartialEq + 'a, + Element<'a, Message<TOption>>: From<&'a TOption>, +{ + pub fn set_options(&mut self, options: Vec<TOption>) -> SetOptionsResult<TOption> { + let active_option_index = + self.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); + self.options_before_active = split.0.to_vec(); + self.options_after_active = split.1.split_at(1).1.to_vec(); + SetOptionsResult::SetOptionsAndKeptSelection + } else { + self.options_before_active = options + .split_last() + .map_or_else(Vec::new, |(_last, rest)| rest.to_vec()); + self.active_option = options.last().cloned(); + options.last().cloned().map_or( + SetOptionsResult::SetOptionsAndKeptSelection, + SetOptionsResult::SetOptionsAndSetSelectedOption, + ) + } + } +} diff --git a/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs b/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs index 15321b7..1d5a734 100644 --- a/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs +++ b/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs @@ -1,6 +1,11 @@ use iced::Element; -use crate::traits::{Component, Navigable, NavigationResult}; +use crate::{ + gui::components::navigation::{ + navigation_select_option::SelectOptionResult, navigation_set_options::SetOptionsResult, + }, + traits::{Component, Navigable, NavigationResult}, +}; use super::{Action, Message, Navigation}; @@ -10,93 +15,25 @@ where 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![]; + Message::SelectOption(option) => match self.select_option(option) { + SelectOptionResult::SelectedExistingOption(option) + | SelectOptionResult::SelectedNewOption(option) => Action::SelectOption(option), + SelectOptionResult::AlreadySelected => Action::None, + }, + + Message::SetOptions(options) => match self.set_options(options) { + SetOptionsResult::SetOptionsAndKeptSelection => Action::None, + SetOptionsResult::SetOptionsAndSetSelectedOption(option) => { 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 => match self.move_next() { NavigationResult::Moved(option) => Action::SelectOption(option), NavigationResult::LastOption => Action::None, }, + Message::SelectPrev => match self.move_prev() { NavigationResult::Moved(option) => Action::SelectOption(option), NavigationResult::LastOption => Action::None, |
