diff options
| author | joeac <me@joeac.net> | 2026-01-17 17:17:50 +0000 |
|---|---|---|
| committer | joeac <me@joeac.net> | 2026-01-17 17:17:50 +0000 |
| commit | bf74f305894bde98033932235a4210c7d6865adf (patch) | |
| tree | 051422c97fcb5d7c2eafd426ea66e1a906948747 /schist_desktop_gui/src/gui/components | |
| parent | fe85652e4d3e8906824baddaafd05d19105579b8 (diff) | |
| parent | f69ec8416c4e6301dcfa06791b025785d7f61b6b (diff) | |
Merge pull request 'random-stuff' (#4) from random-stuff into main
Reviewed-on: https://git.joeac.net/joeac/schist/pulls/4
Diffstat (limited to 'schist_desktop_gui/src/gui/components')
11 files changed, 336 insertions, 349 deletions
diff --git a/schist_desktop_gui/src/gui/components/balances_view.rs b/schist_desktop_gui/src/gui/components/balances_view.rs index 3ca37be..a1c8db3 100644 --- a/schist_desktop_gui/src/gui/components/balances_view.rs +++ b/schist_desktop_gui/src/gui/components/balances_view.rs @@ -3,19 +3,13 @@ mod update_balances_view; mod view_balances_view; mod view_group_names; -use self::{ - update_balances_view::update_balances_view, view_balances_view::view_balances_view, - view_group_names::view_group_names, -}; +use self::view_group_names::view_group_names; use schist_models::Bucket; -use crate::{ - gui::components::{ - balances_view::make_balances_view_greeting::make_balances_view_greeting, navigation, - Navigation, Text, - }, - traits::{Component, Viewable}, +use crate::gui::components::{ + balances_view::make_balances_view_greeting::make_balances_view_greeting, navigation, + Navigation, Text, }; #[derive(Clone, Debug)] @@ -49,15 +43,3 @@ impl BalancesView { } } } - -impl<'a> Viewable<'a, Message> for BalancesView { - fn view(&'a self) -> iced::Element<'a, Message> { - view_balances_view(self) - } -} - -impl<'a> Component<'a, Message, Action> for BalancesView { - fn update(&mut self, message: Message) -> Action { - update_balances_view(self, message) - } -} diff --git a/schist_desktop_gui/src/gui/components/balances_view/update_balances_view.rs b/schist_desktop_gui/src/gui/components/balances_view/update_balances_view.rs index e7b32c3..1dd5c6f 100644 --- a/schist_desktop_gui/src/gui/components/balances_view/update_balances_view.rs +++ b/schist_desktop_gui/src/gui/components/balances_view/update_balances_view.rs @@ -7,42 +7,57 @@ use crate::{ traits::Component, }; -pub fn update_balances_view(balances_view: &mut BalancesView, message: Message) -> Action { - match message { - Message::NavigationMessage(message) => update_navigation(balances_view, message), - Message::SetBuckets(buckets) => set_buckets(balances_view, buckets), - Message::SelectNextBucket => select_next_bucket(balances_view), - Message::SelectPrevBucket => select_prev_bucket(balances_view), +impl<'a> Component<'a, Message, Action> for BalancesView { + fn update(&mut self, message: Message) -> Action { + match message { + Message::NavigationMessage(message) => { + update_navigation(self, message); + Action::None + } + + Message::SetBuckets(buckets) => { + set_buckets(self, buckets); + Action::None + } + + Message::SelectNextBucket => { + select_next_bucket(self); + Action::None + } + + Message::SelectPrevBucket => { + select_prev_bucket(self); + Action::None + } + } } } -fn select_prev_bucket(balances_view: &mut BalancesView) -> Action { +fn select_prev_bucket(balances_view: &mut BalancesView) -> () { match balances_view .navigation .update(navigation::Message::SelectPrev) { navigation::Action::SelectOption(option) => { balances_view.greeting = make_balances_view_greeting(Some(option)); - Action::None } - navigation::Action::None => Action::None, - } + navigation::Action::None => {} + }; } -fn select_next_bucket(balances_view: &mut BalancesView) -> Action { +fn select_next_bucket(balances_view: &mut BalancesView) -> () { match balances_view .navigation .update(navigation::Message::SelectNext) { navigation::Action::SelectOption(option) => { balances_view.greeting = make_balances_view_greeting(Some(option)); - Action::None } - navigation::Action::None => Action::None, - } + navigation::Action::None => {} + }; } -fn set_buckets(balances_view: &mut BalancesView, buckets: Vec<schist_models::Bucket>) -> Action { +fn set_buckets(balances_view: &mut BalancesView, buckets: Vec<schist_models::Bucket>) -> () { balances_view.buckets = buckets.clone(); match balances_view .navigation @@ -50,23 +65,18 @@ fn set_buckets(balances_view: &mut BalancesView, buckets: Vec<schist_models::Buc { navigation::Action::SelectOption(option) => { balances_view.greeting = make_balances_view_greeting(Some(option)); - Action::None } - navigation::Action::None => Action::None, - } + navigation::Action::None => {} + }; } -fn update_navigation( - balances_view: &mut BalancesView, - message: navigation::Message<Text>, -) -> Action { +fn update_navigation(balances_view: &mut BalancesView, message: navigation::Message<Text>) -> () { match balances_view.navigation.update(message) { navigation::Action::SelectOption(group_name) => { balances_view.greeting = make_balances_view_greeting(Some(group_name)); - Action::None } - navigation::Action::None => Action::None, - } + navigation::Action::None => {} + }; } #[cfg(test)] diff --git a/schist_desktop_gui/src/gui/components/balances_view/view_balances_view.rs b/schist_desktop_gui/src/gui/components/balances_view/view_balances_view.rs index 6a64508..22f22b6 100644 --- a/schist_desktop_gui/src/gui/components/balances_view/view_balances_view.rs +++ b/schist_desktop_gui/src/gui/components/balances_view/view_balances_view.rs @@ -1,23 +1,30 @@ -use iced::widget::{column, row, Container}; -use iced::{alignment, Element, Length}; +use iced::{ + alignment, + widget::{column, row, Container}, + Length, +}; -use crate::gui::components::Text; -use crate::gui::components::{balances_view::Message, BalancesView}; -use crate::style::SPACING_LG; -use crate::traits::Viewable; +use crate::{ + gui::components::{balances_view::Message, BalancesView, Text}, + style::SPACING_LG, + traits::Viewable, +}; -pub fn view_balances_view<'a>(balances_view: &'a BalancesView) -> Element<'a, Message> { - let navigation = balances_view - .navigation - .view() - .map(Message::NavigationMessage); - let main_content = column![Text::default(&balances_view.greeting).as_element()]; - row![ - Container::new(navigation).width(Length::FillPortion(1)), - Container::new(main_content).width(Length::FillPortion(3)), - ] - .align_y(alignment::Vertical::Center) - .height(Length::Fill) - .spacing(SPACING_LG) - .into() +impl<'a> Viewable<'a, Message> for BalancesView { + fn view(&'a self) -> iced::Element<'a, Message> { + let balances_view: &'a BalancesView = self; + let navigation = balances_view + .navigation + .view() + .map(Message::NavigationMessage); + let main_content = column![Text::default(&balances_view.greeting).as_element()]; + row![ + Container::new(navigation).width(Length::FillPortion(1)), + Container::new(main_content).width(Length::FillPortion(3)), + ] + .align_y(alignment::Vertical::Center) + .height(Length::Fill) + .spacing(SPACING_LG) + .into() + } } diff --git a/schist_desktop_gui/src/gui/components/bucket_name_and_balance.rs b/schist_desktop_gui/src/gui/components/bucket_name_and_balance.rs index 24a3952..8a5a16e 100644 --- a/schist_desktop_gui/src/gui/components/bucket_name_and_balance.rs +++ b/schist_desktop_gui/src/gui/components/bucket_name_and_balance.rs @@ -1,7 +1,10 @@ -use iced::{widget::row, Element}; +use iced::{ + widget::{row, text}, + Element, Length, +}; use schist_models::Bucket; -use crate::gui::components::{navigation, Text}; +use crate::gui::components::navigation; #[derive(Clone, Debug, PartialEq)] pub struct BucketNameAndBalance { @@ -14,11 +17,21 @@ impl BucketNameAndBalance { } } -impl<'a> Into<Element<'a, navigation::Message<BucketNameAndBalance>>> for BucketNameAndBalance { - fn into(self) -> Element<'a, navigation::Message<BucketNameAndBalance>> { +impl<'a> From<&'a BucketNameAndBalance> for Element<'a, navigation::Message<BucketNameAndBalance>> { + fn from(bucket_name_and_balance: &'a BucketNameAndBalance) -> Self { + let balance_style = if bucket_name_and_balance + .bucket + .balance + .is_none_or(|balance| balance >= 0) + { + text::default + } else { + text::danger + }; + row![ - Text::new(&self.bucket.name).as_element(), - Text::new(&self.bucket.balance.unwrap_or(0).to_string()).as_element(), + text(bucket_name_and_balance.bucket.name.clone()).width(Length::Fill), + text(bucket_name_and_balance.bucket.pretty_balance_per_100()).style(balance_style), ] .into() } diff --git a/schist_desktop_gui/src/gui/components/button.rs b/schist_desktop_gui/src/gui/components/button.rs index e071f33..6882273 100644 --- a/schist_desktop_gui/src/gui/components/button.rs +++ b/schist_desktop_gui/src/gui/components/button.rs @@ -2,9 +2,10 @@ use iced::{widget::Button, Element}; use crate::style::*; -pub fn active_button<'a, Content: Into<Element<'a, Message>>, Message>( - content: Content, -) -> Button<'a, Message> { +pub fn active_button<'a, Content, Message>(content: &'a Content) -> Button<'a, Message> +where + Element<'a, Message>: From<&'a Content>, +{ iced::widget::button(content) .style(|theme: &iced::Theme, _status| iced::widget::button::Style { background: Some(iced::Background::Color( diff --git a/schist_desktop_gui/src/gui/components/navigation.rs b/schist_desktop_gui/src/gui/components/navigation.rs index bed3221..6dbe622 100644 --- a/schist_desktop_gui/src/gui/components/navigation.rs +++ b/schist_desktop_gui/src/gui/components/navigation.rs @@ -1,19 +1,9 @@ -mod new_navigation; mod update_navigation; mod view_navigation; mod view_navigation_button; -use new_navigation::new_navigation; -use update_navigation::update_navigation; -use view_navigation::view_navigation; -use view_navigation_button::view_navigation_button; - use std::fmt::Debug; -use iced::Element; - -use crate::traits::{Component, Viewable}; - #[derive(Clone, Debug)] pub struct Navigation<TOption> { options_before_active: Vec<TOption>, @@ -36,33 +26,67 @@ pub enum Action<TOption> { impl<TOption: Clone + Debug + PartialEq> Navigation<TOption> { pub fn new(active_option: Option<TOption>, options: Vec<TOption>) -> Self { - new_navigation(active_option, options) + let active_option_index = active_option.clone().map_or(Option::None, |active_option| { + options.iter().position(|option| option.eq(&active_option)) + }); + 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(), + active_option: active_option, + options_after_active: split.1.split_at(1).1.to_vec(), + } + } else { + Navigation { + options_before_active: options, + active_option: active_option, + options_after_active: vec![], + } + } } } -impl<'a, TOption> Navigation<TOption> -where - TOption: Clone + PartialEq + Into<Element<'a, Message<TOption>>>, -{ - pub fn button(&'a self, option: &'a TOption) -> Element<'a, Message<TOption>> { - view_navigation_button(self, option) +#[cfg(test)] +mod test { + use super::Navigation; + + #[test] + fn when_active_option_at_start_of_options_then_finds_active_option() { + let navigation = Navigation::new(Some(1), vec![1, 2, 3, 4, 5]); + assert_eq!(Vec::<i32>::new(), navigation.options_before_active); + assert_eq!(Some(1), navigation.active_option); + assert_eq!(vec![2, 3, 4, 5], navigation.options_after_active); } -} -impl<'a, TOption> Viewable<'a, Message<TOption>> for Navigation<TOption> -where - TOption: Clone + PartialEq + Into<Element<'a, Message<TOption>>>, -{ - fn view(&'a self) -> iced::Element<'a, Message<TOption>> { - view_navigation(self) + #[test] + fn when_active_option_in_middle_of_options_then_finds_active_option() { + let navigation = Navigation::new(Some(3), vec![1, 2, 3, 4, 5]); + assert_eq!(vec![1, 2], navigation.options_before_active); + assert_eq!(Some(3), navigation.active_option); + assert_eq!(vec![4, 5], navigation.options_after_active); + } + + #[test] + fn when_active_option_at_end_of_options_then_finds_active_option() { + let navigation = Navigation::new(Some(5), vec![1, 2, 3, 4, 5]); + assert_eq!(vec![1, 2, 3, 4], navigation.options_before_active); + assert_eq!(Some(5), navigation.active_option); + assert_eq!(Vec::<i32>::new(), navigation.options_after_active); + } + + #[test] + fn when_active_option_not_in_options_then_appends_active_option() { + let navigation = Navigation::new(Some(6), vec![1, 2, 3, 4, 5]); + assert_eq!(vec![1, 2, 3, 4, 5], navigation.options_before_active); + assert_eq!(Some(6), navigation.active_option); + assert_eq!(Vec::<i32>::new(), navigation.options_after_active); } -} -impl<'a, TOption> Component<'a, Message<TOption>, Action<TOption>> for Navigation<TOption> -where - TOption: Clone + PartialEq + Into<Element<'a, Message<TOption>>>, -{ - fn update(&mut self, message: Message<TOption>) -> Action<TOption> { - update_navigation(self, message) + #[test] + fn when_no_active_option_then_all_options_are_before_active_option() { + let navigation = Navigation::new(None, vec![1, 2, 3, 4, 5]); + assert_eq!(vec![1, 2, 3, 4, 5], navigation.options_before_active); + assert_eq!(None, navigation.active_option); + assert_eq!(Vec::<i32>::new(), navigation.options_after_active); } } diff --git a/schist_desktop_gui/src/gui/components/navigation/new_navigation.rs b/schist_desktop_gui/src/gui/components/navigation/new_navigation.rs deleted file mode 100644 index b5c0c19..0000000 --- a/schist_desktop_gui/src/gui/components/navigation/new_navigation.rs +++ /dev/null @@ -1,72 +0,0 @@ -use super::Navigation; - -pub fn new_navigation<TOption>( - active_option: Option<TOption>, - options: Vec<TOption>, -) -> Navigation<TOption> -where - TOption: Clone + PartialEq, -{ - let active_option_index = active_option.clone().map_or(Option::None, |active_option| { - options.iter().position(|option| option.eq(&active_option)) - }); - 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(), - active_option, - options_after_active: split.1.split_at(1).1.to_vec(), - } - } else { - Navigation { - options_before_active: options, - active_option, - options_after_active: vec![], - } - } -} - -#[cfg(test)] -mod test { - use super::Navigation; - - #[test] - fn when_active_option_at_start_of_options_then_finds_active_option() { - let navigation = Navigation::new(Some(1), vec![1, 2, 3, 4, 5]); - assert_eq!(Vec::<i32>::new(), navigation.options_before_active); - assert_eq!(Some(1), navigation.active_option); - assert_eq!(vec![2, 3, 4, 5], navigation.options_after_active); - } - - #[test] - fn when_active_option_in_middle_of_options_then_finds_active_option() { - let navigation = Navigation::new(Some(3), vec![1, 2, 3, 4, 5]); - assert_eq!(vec![1, 2], navigation.options_before_active); - assert_eq!(Some(3), navigation.active_option); - assert_eq!(vec![4, 5], navigation.options_after_active); - } - - #[test] - fn when_active_option_at_end_of_options_then_finds_active_option() { - let navigation = Navigation::new(Some(5), vec![1, 2, 3, 4, 5]); - assert_eq!(vec![1, 2, 3, 4], navigation.options_before_active); - assert_eq!(Some(5), navigation.active_option); - assert_eq!(Vec::<i32>::new(), navigation.options_after_active); - } - - #[test] - fn when_active_option_not_in_options_then_appends_active_option() { - let navigation = Navigation::new(Some(6), vec![1, 2, 3, 4, 5]); - assert_eq!(vec![1, 2, 3, 4, 5], navigation.options_before_active); - assert_eq!(Some(6), navigation.active_option); - assert_eq!(Vec::<i32>::new(), navigation.options_after_active); - } - - #[test] - fn when_no_active_option_then_all_options_are_before_active_option() { - let navigation = Navigation::new(None, vec![1, 2, 3, 4, 5]); - assert_eq!(vec![1, 2, 3, 4, 5], navigation.options_before_active); - assert_eq!(None, navigation.active_option); - assert_eq!(Vec::<i32>::new(), navigation.options_after_active); - } -} 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 f86867f..c44ddd8 100644 --- a/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs +++ b/schist_desktop_gui/src/gui/components/navigation/update_navigation.rs @@ -1,127 +1,130 @@ use iced::Element; +use crate::traits::Component; + use super::{Action, Message, Navigation}; -pub fn update_navigation<'a, TOption>( - navigation: &mut Navigation<TOption>, - message: Message<TOption>, -) -> Action<TOption> +impl<'a, TOption> Component<'a, Message<TOption>, Action<TOption>> for Navigation<TOption> where - TOption: Clone + PartialEq + Into<Element<'a, Message<TOption>>>, + TOption: Clone + PartialEq + 'a, + Element<'a, Message<TOption>>: From<&'a TOption>, { - match message { - Message::SelectOption(option) => { - if navigation - .active_option - .as_ref() - .is_some_and(|active_option| active_option.clone() == option) - { - Action::None - } else if let Some(index) = navigation - .options_before_active - .iter() - .position(|o| o.clone() == option) - { - let split = navigation.options_before_active.split_at(index); - navigation.options_after_active = vec![ + 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 - .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| o.clone() == option) - { - let split = navigation.options_after_active.split_at(index); - navigation.options_before_active = vec![ - navigation.options_before_active.clone(), - split.0.to_vec(), + .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(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()); + .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) } - 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::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 + 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 + } } } } diff --git a/schist_desktop_gui/src/gui/components/navigation/view_navigation.rs b/schist_desktop_gui/src/gui/components/navigation/view_navigation.rs index beec818..3f1da18 100644 --- a/schist_desktop_gui/src/gui/components/navigation/view_navigation.rs +++ b/schist_desktop_gui/src/gui/components/navigation/view_navigation.rs @@ -1,26 +1,27 @@ use iced::{widget::column, Element}; +use crate::traits::Viewable; + use super::{Message, Navigation}; -pub fn view_navigation<'a, TOption>( - navigation: &'a Navigation<TOption>, -) -> Element<'a, Message<TOption>> +impl<'a, TOption> Viewable<'a, Message<TOption>> for Navigation<TOption> where - TOption: Clone + PartialEq + Into<Element<'a, Message<TOption>>>, + TOption: Clone + PartialEq + 'a, + Element<'a, Message<TOption>>: From<&'a TOption>, { - let mut options = Vec::new(); - navigation - .options_before_active - .iter() - .map(|option| navigation.button(&option)) - .for_each(|option| options.push(option)); - if let Some(active_option) = navigation.active_option.as_ref() { - options.push(navigation.button(&active_option)); + fn view(&'a self) -> iced::Element<'a, Message<TOption>> { + let mut options = Vec::new(); + self.options_before_active + .iter() + .map(|option| self.view_navigation_button(&option)) + .for_each(|option| options.push(option)); + if let Some(active_option) = self.active_option.as_ref() { + options.push(self.view_navigation_button(&active_option)); + } + self.options_after_active + .iter() + .map(|option| self.view_navigation_button(&option)) + .for_each(|option| options.push(option)); + column(options).into() } - navigation - .options_after_active - .iter() - .map(|option| navigation.button(&option)) - .for_each(|option| options.push(option)); - column(options).into() } diff --git a/schist_desktop_gui/src/gui/components/navigation/view_navigation_button.rs b/schist_desktop_gui/src/gui/components/navigation/view_navigation_button.rs index 3132bf1..d65328c 100644 --- a/schist_desktop_gui/src/gui/components/navigation/view_navigation_button.rs +++ b/schist_desktop_gui/src/gui/components/navigation/view_navigation_button.rs @@ -4,24 +4,24 @@ use crate::gui::components::{active_button, inactive_button}; use super::{Message, Navigation}; -pub fn view_navigation_button<'a, TOption>( - navigation: &'a Navigation<TOption>, - option: &'a TOption, -) -> Element<'a, Message<TOption>> +impl<'a, TOption> Navigation<TOption> where - TOption: Clone + PartialEq + Into<Element<'a, Message<TOption>>>, + TOption: Clone + PartialEq + 'a, + Element<'a, Message<TOption>>: From<&'a TOption>, { - if navigation - .active_option - .as_ref() - .is_some_and(|o| *o == *option) - { - active_button(Into::<Element<'a, Message<TOption>>>::into(option.clone())).into() - } else { - inactive_button( - Into::<Element<'a, Message<TOption>>>::into(option.clone()), - Message::SelectOption(option.clone()), - ) + pub(super) fn view_navigation_button( + &'a self, + option: &'a TOption, + ) -> Element<'a, Message<TOption>> { + if self + .active_option + .as_ref() + .is_some_and(|o| TOption::eq(o, option)) + { + active_button(option) + } else { + inactive_button(option, Message::SelectOption(option.clone())) + } .into() } } diff --git a/schist_desktop_gui/src/gui/components/text.rs b/schist_desktop_gui/src/gui/components/text.rs index 90cd7bc..a3093ac 100644 --- a/schist_desktop_gui/src/gui/components/text.rs +++ b/schist_desktop_gui/src/gui/components/text.rs @@ -1,3 +1,5 @@ +use std::borrow::Borrow; + use crate::style::*; #[derive(Clone, Debug, PartialEq)] @@ -71,30 +73,46 @@ impl Text { } } -impl<'a, Message> Into<iced::Element<'a, Message>> for Text { - fn into(self) -> iced::Element<'a, Message> { - iced::widget::text(self.content.clone()) - .size(match self.size { - Some(Size::Small) => TEXT_SIZE_SM, - Some(Size::Base) | None => TEXT_SIZE_BASE, - }) - .style(move |theme: &iced::Theme| iced::widget::text::Style { - color: match (&self.colour, &self.strength) { - (Some(Colour::Danger), Some(Strength::Base) | None) => { - Some(theme.extended_palette().danger.base.text) - } - (Some(Colour::Danger), Some(Strength::Weak)) => { - Some(theme.extended_palette().danger.weak.text) - } - (Some(Colour::Primary), Some(Strength::Base) | None) => { - Some(theme.extended_palette().primary.base.text) - } - (Some(Colour::Primary), Some(Strength::Weak)) => { - Some(theme.extended_palette().primary.weak.text) - } - (None, _) => None, - }, - }) - .into() +impl<'a, Message> From<Text> for iced::Element<'a, Message> { + fn from(text: Text) -> Self { + text_as_element(text) + } +} + +impl<'a, Message> From<&'a Text> for iced::Element<'a, Message> { + fn from(text: &'a Text) -> Self { + text_as_element(text) } } + +fn text_as_element<'a, T, Message>(text: T) -> iced::Element<'a, Message> +where + T: Borrow<Text> + 'a, +{ + iced::widget::text(text.borrow().content.clone()) + .size(match text.borrow().size { + Some(Size::Small) => TEXT_SIZE_SM, + Some(Size::Base) | None => TEXT_SIZE_BASE, + }) + .style(move |theme: &iced::Theme| iced::widget::text::Style { + color: match ( + &text.borrow().borrow().colour, + &text.borrow().borrow().strength, + ) { + (Some(Colour::Danger), Some(Strength::Base) | None) => { + Some(theme.extended_palette().danger.base.text) + } + (Some(Colour::Danger), Some(Strength::Weak)) => { + Some(theme.extended_palette().danger.weak.text) + } + (Some(Colour::Primary), Some(Strength::Base) | None) => { + Some(theme.extended_palette().primary.base.text) + } + (Some(Colour::Primary), Some(Strength::Weak)) => { + Some(theme.extended_palette().primary.weak.text) + } + (None, _) => None, + }, + }) + .into() +} |
