summaryrefslogtreecommitdiff
path: root/schist_desktop_gui/src/gui
diff options
context:
space:
mode:
authorJoe Carstairs <me@joeac.net>2026-01-25 10:18:50 +0000
committerJoe Carstairs <me@joeac.net>2026-01-25 10:32:55 +0000
commit409b5bc15951001c6d16c2bcfa747fda25cb3735 (patch)
tree3e52708e287a74dc20e4868a6e0e7a5e1dcd492f /schist_desktop_gui/src/gui
parent1feae160bd184dcea618415c0e9e55289ca8b68a (diff)
tidier impl of Component for Navigation
Diffstat (limited to 'schist_desktop_gui/src/gui')
-rw-r--r--schist_desktop_gui/src/gui/components/navigation.rs2
-rw-r--r--schist_desktop_gui/src/gui/components/navigation/navigation_select_option.rs71
-rw-r--r--schist_desktop_gui/src/gui/components/navigation/navigation_set_options.rs40
-rw-r--r--schist_desktop_gui/src/gui/components/navigation/update_navigation.rs99
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,