Skip to main content

ferrix_app/widgets/
table.rs

1/* table.rs
2 *
3 * Copyright 2025 Michail Krasnov <mskrasnov07@ya.ru>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21//! Custom table widget
22
23use iced::widget::button;
24use iced::widget::text::IntoFragment;
25use iced::{
26    Element, Length,
27    widget::{table, text},
28};
29
30use crate::messages::ButtonsMessage;
31use crate::{Message, fl, widgets::link_button};
32
33#[derive(Debug, Clone)]
34pub struct InfoRow<V> {
35    pub param_header: String,
36    pub value: Option<V>,
37}
38
39impl<V> InfoRow<V> {
40    pub fn new<P>(param: P, value: Option<V>) -> Self
41    where
42        P: Into<String>,
43        V: ToString,
44    {
45        Self {
46            param_header: param.into(),
47            value,
48        }
49    }
50}
51
52pub fn kv_info_table<'a, V>(rows: Vec<InfoRow<V>>) -> Element<'a, Message>
53where
54    V: ToString + Clone + 'a,
55{
56    let columns = [
57        table::column(hdr_name(fl!("hdr-param")), |row: InfoRow<V>| {
58            text(row.param_header)
59        }),
60        table::column(hdr_name(fl!("hdr-value")), |row: InfoRow<V>| {
61            text_fmt_val(row.value)
62        })
63        .width(Length::Fill),
64    ];
65
66    table(columns, rows).padding(2).width(Length::Fill).into()
67}
68
69pub fn text_fmt_val<'a, V>(val: Option<V>) -> Element<'a, Message>
70where
71    V: ToString + 'a,
72{
73    match val {
74        Some(val) if !val.to_string().is_empty() && !val.to_string().contains("http") => {
75            button(text(val.to_string()))
76                .style(button::text)
77                .padding(0)
78                .on_press(Message::Buttons(ButtonsMessage::CopyButtonPressed(
79                    val.to_string(),
80                )))
81                .into()
82        }
83        Some(val) if !val.to_string().is_empty() && val.to_string().contains("http") => {
84            link_button(val.to_string(), val.to_string()).into()
85        }
86        Some(_) => text("N/A").into(),
87        None => text("").into(),
88    }
89}
90
91pub fn hdr_name<'a, S: IntoFragment<'a>>(s: S) -> text::Text<'a> {
92    text(s).style(text::secondary)
93}
94
95pub fn fmt_val<T>(val: Option<T>) -> Option<String>
96where
97    T: ToString + Copy,
98{
99    match val {
100        Some(val) => Some(val.to_string()),
101        None => None,
102    }
103}
104
105pub fn fmt_vec<T>(val: &Option<Vec<T>>) -> Option<String>
106where
107    T: ToString + Clone,
108{
109    match val {
110        Some(val) => {
111            let mut s = String::new();
112            for i in val {
113                s = format!("{s}{} ", i.to_string());
114            }
115            Some(s)
116        }
117        None => None,
118    }
119}
120
121pub fn fmt_bool(val: Option<bool>) -> Option<String> {
122    match val {
123        Some(val) => match val {
124            true => Some(fl!("bool-true")),
125            false => Some(fl!("bool-false")),
126        },
127        None => None,
128    }
129}