1use iced::Alignment::Center;
24use iced::widget::svg::Handle;
25use iced::widget::text::IntoFragment;
26use iced::widget::{Column, row, rule, tooltip};
27use iced::{Border, Element, Theme};
28use iced::{
29 Color,
30 widget::{button, column, container, svg, text, tooltip::Position},
31};
32
33pub mod line_charts;
34pub mod table;
35
36use crate::{
37 icons::{ABOUT_ICON, ERROR_ICON, EXPORT_ICON, SETTINGS_ICON},
38 messages::{ButtonsMessage, Message},
39 pages::Page,
40};
41
42pub fn icon_tooltip<'a, T>(icon_name: &'a str, tooltip: T) -> container::Container<'a, Message>
43where
44 T: IntoFragment<'a>,
45{
46 let svg_bytes = match icon_name {
47 "about" => ABOUT_ICON,
48 "error" => ERROR_ICON,
49 "export" => EXPORT_ICON,
50 "settings" => SETTINGS_ICON,
51 _ => &[],
52 };
53 let icon = svg(Handle::from_memory(svg_bytes))
54 .style(|theme: &iced::Theme, _| svg::Style {
55 color: Some(theme.palette().text),
56 })
57 .width(16)
58 .height(16);
59
60 container(iced::widget::tooltip(
61 icon,
62 container(text(tooltip).style(|s: &iced::Theme| text::Style {
63 color: Some(if s.extended_palette().is_dark {
64 s.palette().text
65 } else {
66 Color::WHITE
67 }),
68 }))
69 .padding(2)
70 .style(|_| container::Style {
71 background: Some(iced::Background::Color(Color::from_rgba8(0, 0, 0, 0.71))),
72 border: iced::Border {
73 radius: iced::border::Radius::from(2),
74 ..iced::Border::default()
75 },
76 ..Default::default()
77 }),
78 Position::Bottom,
79 ))
80 .width(16)
81 .height(16)
82}
83
84pub fn icon_button<'a>(icon_name: &'a str, tooltip: String) -> button::Button<'a, Message> {
85 let svg_bytes = match icon_name {
86 "about" => ABOUT_ICON,
87 "error" => ERROR_ICON,
88 "export" => EXPORT_ICON,
89 "settings" => SETTINGS_ICON,
90 _ => &[],
91 };
92 let icon = svg(Handle::from_memory(svg_bytes)).style(|theme: &iced::Theme, _| svg::Style {
93 color: Some(theme.palette().text),
94 });
95
96 button(iced::widget::tooltip(
97 icon.width(16).height(16),
98 container(text(tooltip).size(11).style(|s: &iced::Theme| text::Style {
99 color: Some(if s.extended_palette().is_dark {
100 s.palette().text
101 } else {
102 Color::WHITE
103 }),
104 }))
105 .padding(2)
106 .style(|_| container::Style {
107 background: Some(iced::Background::Color(Color::from_rgba8(0, 0, 0, 0.71))),
108 border: iced::Border {
109 radius: iced::border::Radius::from(2),
110 ..iced::Border::default()
111 },
112 ..Default::default()
113 }),
114 Position::Bottom,
115 ))
116 .style(button::subtle)
117 .padding(2)
118}
119
120pub fn sidebar_button<'a>(page: Page, cur_page: Page) -> button::Button<'a, Message> {
121 button(text(page.title_str()))
122 .style(if page != cur_page {
123 button::subtle
124 } else {
125 button::secondary
126 })
127 .on_press(Message::SelectPage(page))
128}
129
130pub fn link_button<'a, P, L>(placeholder: P, link: L) -> tooltip::Tooltip<'a, Message>
131where
132 P: IntoFragment<'a>,
133 L: ToString + IntoFragment<'a> + 'a,
134{
135 tooltip(
136 button(text(placeholder))
137 .style(super::styles::link_button)
138 .padding(0)
139 .on_press(Message::Buttons(ButtonsMessage::LinkButtonPressed(
140 link.to_string(),
141 ))),
142 container(text(link).size(11).style(|s: &iced::Theme| text::Style {
143 color: Some(if s.extended_palette().is_dark {
144 s.palette().text
145 } else {
146 Color::WHITE
147 }),
148 }))
149 .padding(2)
150 .style(|_| container::Style {
151 background: Some(iced::Background::Color(Color::from_rgba8(0, 0, 0, 0.71))),
152 border: iced::Border {
153 radius: iced::border::Radius::from(2),
154 ..iced::Border::default()
155 },
156 ..Default::default()
157 }),
158 Position::Bottom,
159 )
160}
161
162pub fn header<'a, T>(txt: T) -> row::Row<'a, Message>
163where
164 T: IntoFragment<'a> + 'a,
165{
166 row![text(txt).size(16), rule::horizontal(1),]
167 .spacing(5)
168 .align_y(Center)
169}
170
171pub fn header_text<'a>(txt: String) -> Column<'a, Message> {
172 column![text(txt).size(22), rule::horizontal(1)].spacing(2)
173}
174
175pub fn category_header<'a, T>(txt: T) -> text::Text<'a>
176where
177 T: IntoFragment<'a> + 'a,
178{
179 text(txt).size(14).style(|t: &Theme| {
180 let palette = t.palette();
181 let text_color = palette.text.scale_alpha(0.7);
182
183 let mut style = text::Style::default();
184 style.color = Some(text_color);
185
186 style
187 })
188}
189
190pub fn glassy_container<'a, T, C>(header: T, content: C) -> container::Container<'a, Message>
191where
192 T: IntoFragment<'a> + 'a,
193 C: Into<Element<'a, Message>> + 'a,
194{
195 container(column![category_header(header), content.into()].spacing(5))
196 .padding(5)
197 .style(|t| {
198 let palette = t.palette();
199 let bg = palette.text.scale_alpha(0.03);
200 let border_color = palette.text.scale_alpha(0.08);
201
202 container::Style::default().background(bg).border(Border {
203 color: border_color,
204 width: 1.,
205 radius: 5.0.into(),
206 })
207 })
208}