egui_toast/
toast.rs

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    /// Close the toast immediately
54    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    /// Whether the toast should include an icon.
83    pub show_icon: bool,
84    /// Whether the toast should visualize the remaining time
85    pub show_progress: bool,
86    /// The toast is removed when this reaches zero.
87    pub(crate) ttl_sec: f64,
88    /// Initial value of ttl_sec, used for progress
89    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    /// Set duration of the toast. [None] duration means the toast never expires.
105    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    /// Set duration of the toast in milliseconds.
114    pub fn duration_in_millis(self, millis: u64) -> Self {
115        self.duration(Duration::from_millis(millis))
116    }
117
118    /// Set duration of the toast in seconds.
119    pub fn duration_in_seconds(self, secs: f64) -> Self {
120        self.duration(Duration::from_secs_f64(secs))
121    }
122
123    /// Visualize remaining time using a progress bar.
124    pub fn show_progress(mut self, show_progress: bool) -> Self {
125        self.show_progress = show_progress;
126        self
127    }
128
129    /// Show type icon in the toast.
130    pub fn show_icon(mut self, show_icon: bool) -> Self {
131        self.show_icon = show_icon;
132        self
133    }
134
135    /// Remaining time of the toast between 1..0
136    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}