diff options
| author | Joe Carstairs <me@joeac.net> | 2026-02-12 20:00:26 +0000 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2026-02-12 20:00:26 +0000 |
| commit | 413afad1fdf1d15fefc1b709f2eba1332a110608 (patch) | |
| tree | d11385e53035a1d517154f25c72cd64ca9815d1e /schist_desktop_gui/src/gui | |
| parent | b3f91aef7c9673c180690f6e22984d50e0dbeecf (diff) | |
task-085: uses new iced::widget::Table instead of home-made widget
Diffstat (limited to 'schist_desktop_gui/src/gui')
6 files changed, 93 insertions, 171 deletions
diff --git a/schist_desktop_gui/src/gui/components.rs b/schist_desktop_gui/src/gui/components.rs index ec91951..606c418 100644 --- a/schist_desktop_gui/src/gui/components.rs +++ b/schist_desktop_gui/src/gui/components.rs @@ -5,7 +5,6 @@ pub mod buckets_view; pub mod button; pub mod navigation; pub mod panel; -pub mod table; pub mod text; pub mod transactions_view; @@ -16,6 +15,5 @@ pub use buckets_view::BucketsView; pub use button::{button, panel_button}; pub use navigation::Navigation; pub use panel::Panel; -pub use table::Table; pub use text::Text; pub use transactions_view::TransactionsView; diff --git a/schist_desktop_gui/src/gui/components/table.rs b/schist_desktop_gui/src/gui/components/table.rs deleted file mode 100644 index 68090c1..0000000 --- a/schist_desktop_gui/src/gui/components/table.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::collections::HashMap; - -mod view_table; - -#[derive(Clone, Debug, Default)] -pub struct Table<Ix> -where - Ix: Clone + std::fmt::Debug, -{ - pub cols: Vec<Column<Ix>>, - pub rows: Vec<HashMap<Ix, Value>>, -} - -#[derive(Clone, Debug)] -pub enum Value { - String(String), - Currency(i32), -} - -#[derive(Clone, Debug)] -pub struct Column<Ix> -where - Ix: Clone + std::fmt::Debug, -{ - pub index: Ix, - pub name: String, - pub width: f32, -} - -impl<Ix> Column<Ix> -where - Ix: Clone + std::fmt::Debug, -{ - pub fn new(index: Ix, name: &str) -> Self { - Self { - index, - name: name.to_string(), - width: 128.0, - } - } - - pub fn width(&self, width: f32) -> Self { - Self { - width, - ..self.clone() - } - } - - pub fn mul_width(&self, mul: f32) -> Self { - self.width(self.width * mul) - } -} - -#[derive(Clone, Debug)] -pub enum Message {} diff --git a/schist_desktop_gui/src/gui/components/table/view_table.rs b/schist_desktop_gui/src/gui/components/table/view_table.rs deleted file mode 100644 index f082b83..0000000 --- a/schist_desktop_gui/src/gui/components/table/view_table.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::{fmt::Debug, hash::Hash}; - -use iced::widget::{ - column, container, row, scrollable, scrollable::Direction as ScrollableDirection, -}; - -use crate::{gui::components::Text, style::SPACING_MD, traits::Viewable}; - -use super::{Message, Table, Value}; - -impl<'a, Ix> Viewable<'a, Message> for Table<Ix> -where - Ix: Clone + Debug + Eq + Hash, -{ - fn view(&'a self) -> iced::Element<'a, Message> { - let headers = row(self.cols.iter().map(|col| { - container(Text::default(&col.name)) - .width(iced::Length::Fixed(col.width)) - .into() - })) - .spacing(u32::from(SPACING_MD)); - - let rows = column(self.rows.iter().map(|row_data| { - row(self.cols.iter().map(|col| { - container( - row_data - .get(&col.index) - .map(|datum| match datum { - Value::String(text) => format_string(text), - Value::Currency(amount) => format_currency(*amount), - }) - .unwrap_or_else(|| Text::default("")), - ) - .width(iced::Length::Fixed(col.width)) - .into() - })) - .spacing(u32::from(SPACING_MD)) - .into() - })); - - scrollable(column![headers, rows].spacing(u32::from(SPACING_MD))) - .direction(ScrollableDirection::Both { - horizontal: Default::default(), - vertical: Default::default(), - }) - .into() - } -} - -fn format_string(text: &String) -> Text { - Text::default(text).weak().small().clip() -} - -fn format_currency(amount: i32) -> Text { - let text = if amount >= 0 { - format!(" {} · {} ", amount / 100, amount % 100) - } else { - format!("({} · {})", -amount / 100, -amount % 100) - }; - format_string(&text).align_right().width(iced::Length::Fill) -} diff --git a/schist_desktop_gui/src/gui/components/text.rs b/schist_desktop_gui/src/gui/components/text.rs index 7a685c1..1760f4c 100644 --- a/schist_desktop_gui/src/gui/components/text.rs +++ b/schist_desktop_gui/src/gui/components/text.rs @@ -75,6 +75,15 @@ impl Text { } } + pub fn currency(amount: i32) -> Self { + let formatted_string = if amount < 0 { + format!("({} · {})", -amount / 100, -amount % 100) + } else { + format!(" {} · {} ", amount / 100, amount % 100) + }; + Self::default(&formatted_string) + } + pub fn as_element<'a, Message>(self) -> iced::Element<'a, Message> where Message: 'a, diff --git a/schist_desktop_gui/src/gui/components/transactions_view.rs b/schist_desktop_gui/src/gui/components/transactions_view.rs index 51877cf..491049d 100644 --- a/schist_desktop_gui/src/gui/components/transactions_view.rs +++ b/schist_desktop_gui/src/gui/components/transactions_view.rs @@ -6,14 +6,13 @@ use itertools::Itertools; use schist_models::{Account, Transaction}; use crate::{ - gui::components::{navigation, table, AccountNavigationEntry, Navigation, Table}, + gui::components::{navigation, AccountNavigationEntry, Navigation}, traits::Component, }; #[derive(Clone, Debug)] pub struct TransactionsView { navigation: Navigation<AccountNavigationEntry>, - table: Table<i32>, transactions_by_account_id: HashMap<i32, Vec<Transaction>>, } @@ -24,7 +23,6 @@ pub enum Message { SelectPrevAccount, SetAccounts(Vec<Account>), SetTransactions(Vec<Transaction>), - TableMessage(table::Message), } pub enum Action { @@ -42,55 +40,13 @@ impl TransactionsView { account_navigation_entries.first().cloned(), account_navigation_entries, ); - let mut transactions_view = Self { + Self { navigation: navigation, - table: Table::default(), transactions_by_account_id: transactions .into_iter() .cloned() .into_group_map_by(|t| t.account_id), - }; - transactions_view.refresh_table(); - transactions_view - } - - fn refresh_table(&mut self) { - self.table = - Table { - cols: vec![ - table::Column::new(0, "Date"), - table::Column::new(1, "Bucket"), - table::Column::new(2, "Payee").mul_width(2.0), - table::Column::new(3, "Quantity").mul_width(0.67), - table::Column::new(4, "Balance").mul_width(0.67), - ], - rows: self.navigation.active_option.clone().map_or_else( - Vec::new, - |AccountNavigationEntry { account, .. }| { - self.transactions_by_account_id - .get(&account.id) - .cloned() - .unwrap_or_else(Vec::new) - .iter() - .map(|t| { - HashMap::from([ - (0, table::Value::String(t.date.to_string())), - ( - 1, - table::Value::String(t.bucket_id.map_or_else( - || String::from("None"), - |id| id.to_string(), - )), - ), - (2, table::Value::String(t.counterparty.clone())), - (3, table::Value::Currency(t.amount)), - (4, table::Value::String(String::from("TODO"))), - ]) - }) - .collect() - }, - ), - }; + } } } @@ -110,7 +66,6 @@ impl<'a> Component<'a, Message, Action> for TransactionsView { Message::SetTransactions(transactions) => { self.transactions_by_account_id = transactions.into_iter().into_group_map_by(|t| t.account_id); - self.refresh_table(); Action::None } @@ -128,7 +83,6 @@ impl TransactionsView { ) -> Action { match self.navigation.update(message) { navigation::Action::ActivateOption(_) | navigation::Action::SelectOption(_) => { - self.refresh_table(); Action::None } navigation::Action::None => Action::None, diff --git a/schist_desktop_gui/src/gui/components/transactions_view/view_transactions_view.rs b/schist_desktop_gui/src/gui/components/transactions_view/view_transactions_view.rs index 8102314..72f4c8f 100644 --- a/schist_desktop_gui/src/gui/components/transactions_view/view_transactions_view.rs +++ b/schist_desktop_gui/src/gui/components/transactions_view/view_transactions_view.rs @@ -1,10 +1,17 @@ use iced::{ alignment, - widget::{row, Container}, + widget::{ + row, + scrollable::{self, Scrollbar}, + table, + table::column, + Container, Scrollable, + }, Element, Length, }; +use schist_models::Transaction; -use crate::{style::SPACING_LG, traits::Viewable}; +use crate::{gui::components::Text, style::SPACING_LG, traits::Viewable}; use super::{Message, TransactionsView}; @@ -12,11 +19,81 @@ impl<'a> Viewable<'a, Message> for TransactionsView { fn view(&'a self) -> Element<'a, Message> { let navigation = self.navigation.view().map(Message::NavigationMessage); - let table = self.table.view().map(Message::TableMessage); + let columns = [ + column( + Text::default("Date").width(iced::Length::Fixed(128.0)), + |t: Transaction| { + Text::default(t.date.to_string().as_str()) + .width(iced::Length::Fixed(128.0)) + .small() + .clip() + }, + ), + column( + Text::default("Bucket").width(iced::Length::Fixed(128.0)), + |t: Transaction| { + Text::default( + t.bucket_id + .map(|id| id.to_string()) + .unwrap_or(String::from("None")) + .as_str(), + ) + .width(iced::Length::Fixed(128.0)) + .small() + .clip() + }, + ), + column( + Text::default("Payee").width(iced::Length::Fixed(256.0)), + |t: Transaction| { + Text::default(&t.counterparty) + .width(iced::Length::Fixed(256.0)) + .small() + .clip() + }, + ), + column( + Text::default("Quantity").width(iced::Length::Fixed(96.0)), + |t: Transaction| { + Text::currency(t.amount) + .width(iced::Length::Fixed(96.0)) + .small() + .clip() + .align_right() + }, + ), + column( + Text::default("Balance").width(iced::Length::Fixed(96.0)), + |_t: Transaction| { + Text::default("TODO") + .width(iced::Length::Fixed(96.0)) + .small() + .clip() + }, + ), + ]; + + let rows = self + .navigation + .active_option + .clone() + .map_or_else(Vec::default, |option| { + self.transactions_by_account_id + .get(&option.account.id) + .cloned() + .unwrap_or_else(Vec::default) + }); + + let table = table(columns, rows); row![ Container::new(navigation).width(Length::FillPortion(1)), - Container::new(table).width(Length::FillPortion(3)), + Scrollable::new(table) + .direction(scrollable::Direction::Both { + horizontal: Scrollbar::default(), + vertical: Scrollbar::default(), + }) + .width(Length::FillPortion(3)), ] .align_y(alignment::Vertical::Center) .height(Length::Fill) |
