egui_charts/ui_kit/notifications/
toast.rs1use std::sync::atomic::{AtomicU64, Ordering};
6
7use egui::Color32;
8
9use crate::icons::{Icon, icons};
10use crate::theme::UiColors;
11
12static TOAST_ID_COUNTER: AtomicU64 = AtomicU64::new(0);
14
15fn next_toast_id() -> u64 {
17 TOAST_ID_COUNTER.fetch_add(1, Ordering::Relaxed)
18}
19
20#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
22pub enum ToastKind {
23 #[default]
25 Info,
26 Success,
28 Warning,
30 Error,
32}
33
34impl ToastKind {
35 pub fn color(&self, ui: &UiColors) -> Color32 {
37 match self {
38 ToastKind::Info => ui.info,
39 ToastKind::Success => ui.success,
40 ToastKind::Warning => ui.warning,
41 ToastKind::Error => ui.error,
42 }
43 }
44
45 pub fn icon(&self) -> &'static Icon {
47 match self {
48 ToastKind::Info => &icons::INFO,
49 ToastKind::Success => &icons::SUCCESS,
50 ToastKind::Warning => &icons::WARNING,
51 ToastKind::Error => &icons::STATUS_ERROR,
52 }
53 }
54}
55
56#[derive(Clone, Debug)]
58pub struct TradingToast {
59 pub symbol: String,
61 pub logo: Option<String>,
64 pub side: crate::model::OrderSide,
66 pub quantity: f64,
68 pub price: String,
70 pub executed: bool,
72}
73
74#[derive(Clone, Debug)]
76pub struct Toast {
77 pub id: u64,
79 pub kind: ToastKind,
81 pub message: String,
83 pub title: Option<String>,
85 pub trading: Option<TradingToast>,
87 pub duration: f32,
89 pub created_at: f64,
91 pub dismissible: bool,
93}
94
95impl Toast {
96 pub fn new(kind: ToastKind, message: impl Into<String>) -> Self {
98 Self {
99 id: next_toast_id(),
100 kind,
101 message: message.into(),
102 title: None,
103 trading: None,
104 duration: 5.0, created_at: 0.0,
106 dismissible: true,
107 }
108 }
109
110 pub fn info(message: impl Into<String>) -> Self {
112 Self::new(ToastKind::Info, message)
113 }
114
115 pub fn success(message: impl Into<String>) -> Self {
117 Self::new(ToastKind::Success, message)
118 }
119
120 pub fn warning(message: impl Into<String>) -> Self {
122 Self::new(ToastKind::Warning, message)
123 }
124
125 pub fn error(message: impl Into<String>) -> Self {
127 Self::new(ToastKind::Error, message)
128 }
129
130 pub fn with_title(mut self, title: impl Into<String>) -> Self {
132 self.title = Some(title.into());
133 self
134 }
135
136 pub fn duration(mut self, seconds: f32) -> Self {
138 self.duration = seconds;
139 self
140 }
141
142 pub fn permanent(mut self) -> Self {
144 self.duration = 0.0;
145 self
146 }
147
148 pub fn dismissible(mut self, dismissible: bool) -> Self {
150 self.dismissible = dismissible;
151 self
152 }
153
154 pub fn is_expired(&self, current_time: f64) -> bool {
156 if self.duration <= 0.0 {
157 return false; }
159 current_time - self.created_at >= self.duration as f64
160 }
161
162 pub fn remaining_fraction(&self, current_time: f64) -> f32 {
164 if self.duration <= 0.0 {
165 return 1.0; }
167 let elapsed = current_time - self.created_at;
168 (1.0 - (elapsed / self.duration as f64) as f32).clamp(0.0, 1.0)
169 }
170}