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