1use egui::{Color32, WidgetText};
2use std::time::Duration;
3
4#[derive(Default, Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
5pub enum ToastKind {
6 #[default]
7 Info,
8 Warning,
9 Error,
10 Success,
11 Custom(u32),
12}
13
14impl From<u32> for ToastKind {
15 fn from(value: u32) -> ToastKind {
16 ToastKind::Custom(value)
17 }
18}
19
20#[derive(Clone, Default)]
21pub struct Toast {
22 pub kind: ToastKind,
23 pub text: WidgetText,
24 pub options: ToastOptions,
25 pub style: ToastStyle,
26}
27
28impl Toast {
29 pub fn new() -> Self {
30 Self::default()
31 }
32
33 pub fn kind(mut self, kind: ToastKind) -> Self {
34 self.kind = kind;
35 self
36 }
37
38 pub fn text(mut self, text: impl Into<WidgetText>) -> Self {
39 self.text = text.into();
40 self
41 }
42
43 pub fn options(mut self, options: ToastOptions) -> Self {
44 self.options = options;
45 self
46 }
47
48 pub fn style(mut self, style: ToastStyle) -> Self {
49 self.style = style;
50 self
51 }
52
53 pub fn close(&mut self) {
55 self.options.ttl_sec = 0.0;
56 }
57}
58
59#[derive(Clone)]
60pub struct ToastStyle {
61 pub info_icon: WidgetText,
62 pub warning_icon: WidgetText,
63 pub error_icon: WidgetText,
64 pub success_icon: WidgetText,
65 pub close_button_text: WidgetText,
66}
67
68impl Default for ToastStyle {
69 fn default() -> Self {
70 Self {
71 info_icon: WidgetText::from("ℹ").color(Color32::from_rgb(0, 155, 255)),
72 warning_icon: WidgetText::from("⚠").color(Color32::from_rgb(255, 212, 0)),
73 error_icon: WidgetText::from("❗").color(Color32::from_rgb(255, 32, 0)),
74 success_icon: WidgetText::from("✔").color(Color32::from_rgb(0, 255, 32)),
75 close_button_text: WidgetText::from("🗙"),
76 }
77 }
78}
79
80#[derive(Debug, Copy, Clone)]
81pub struct ToastOptions {
82 pub show_icon: bool,
84 pub show_progress: bool,
86 pub(crate) ttl_sec: f64,
88 pub(crate) initial_ttl_sec: f64,
90}
91
92impl Default for ToastOptions {
93 fn default() -> Self {
94 Self {
95 show_icon: true,
96 show_progress: true,
97 ttl_sec: f64::INFINITY,
98 initial_ttl_sec: f64::INFINITY,
99 }
100 }
101}
102
103impl ToastOptions {
104 pub fn duration(mut self, duration: impl Into<Option<Duration>>) -> Self {
106 self.ttl_sec = duration
107 .into()
108 .map_or(f64::INFINITY, |duration| duration.as_secs_f64());
109 self.initial_ttl_sec = self.ttl_sec;
110 self
111 }
112
113 pub fn duration_in_millis(self, millis: u64) -> Self {
115 self.duration(Duration::from_millis(millis))
116 }
117
118 pub fn duration_in_seconds(self, secs: f64) -> Self {
120 self.duration(Duration::from_secs_f64(secs))
121 }
122
123 pub fn show_progress(mut self, show_progress: bool) -> Self {
125 self.show_progress = show_progress;
126 self
127 }
128
129 pub fn show_icon(mut self, show_icon: bool) -> Self {
131 self.show_icon = show_icon;
132 self
133 }
134
135 pub fn progress(self) -> f64 {
137 if self.ttl_sec.is_finite() && self.initial_ttl_sec > 0.0 {
138 self.ttl_sec / self.initial_ttl_sec
139 } else {
140 0.0
141 }
142 }
143}