use std::hash::Hash;
use egui::{Button, Color32, CornerRadius, Frame, Label, Margin, RichText, Stroke, Ui, Widget};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AlertLevel {
Success,
Info,
Warning,
Error,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Alert {
level: AlertLevel,
color: Color32,
message: String,
inner_margin: i8,
outer_margin: i8,
corner_radius: u8,
can_close: bool,
width: Option<f32>,
}
impl Hash for Alert {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.level.hash(state);
self.color.hash(state);
self.message.hash(state);
self.inner_margin.hash(state);
self.outer_margin.hash(state);
self.corner_radius.hash(state);
self.can_close.hash(state);
self.width.unwrap_or(-1.0).to_bits().hash(state);
}
}
impl Default for Alert {
fn default() -> Self {
Alert {
level: AlertLevel::Info,
color: Color32::from_rgb(255, 200, 200),
message: "No message provided".to_string(),
inner_margin: 10,
outer_margin: 1,
corner_radius: 4,
can_close: true, width: None,
}
}
}
impl Alert {
pub fn new(message: &str) -> Self {
let level = AlertLevel::Info;
let color = Self::level_to_color(level);
Self {
level,
color,
message: message.to_string(),
..Default::default()
}
}
pub fn with_level(mut self, level: AlertLevel) -> Self {
self.level = level;
self.color = Self::level_to_color(level);
self
}
pub fn inner_margin(mut self, margin: i8) -> Self {
self.inner_margin = margin;
self
}
pub fn outer_margin(mut self, margin: i8) -> Self {
self.outer_margin = margin;
self
}
pub fn corner_radius(mut self, radius: u8) -> Self {
self.corner_radius = radius;
self
}
pub fn can_close(mut self, closeable: bool) -> Self {
self.can_close = closeable;
self
}
pub fn width(mut self, width: f32) -> Self {
self.width = Some(width);
self
}
fn level_to_color(level: AlertLevel) -> Color32 {
match level {
AlertLevel::Success => Color32::LIGHT_GREEN,
AlertLevel::Info => Color32::LIGHT_BLUE,
AlertLevel::Warning => Color32::LIGHT_YELLOW,
AlertLevel::Error => Color32::LIGHT_RED,
}
}
pub fn get_message(&self) -> &str {
&self.message
}
pub fn get_level(&self) -> AlertLevel {
self.level
}
}
impl Widget for Alert {
fn ui(self, ui: &mut Ui) -> egui::Response {
ui.set_width(self.width.unwrap_or(ui.available_width()));
Frame::default()
.fill(self.color)
.stroke(Stroke::new(1.0, Color32::from_rgb(200, 200, 200)))
.corner_radius(CornerRadius::same(self.corner_radius))
.inner_margin(Margin::same(self.inner_margin))
.outer_margin(Margin::same(self.outer_margin))
.show(ui, |ui| {
ui.horizontal(|ui| {
if self.can_close {
let _r2 = ui.add_enabled(
false,
Label::new(RichText::new(&self.message).color(Color32::BLACK)).wrap(),
);
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.add(
Button::new(RichText::new("X").color(Color32::DARK_RED).strong())
.frame(false),
)
})
.inner
} else {
let label_resp = ui.add_enabled(
false,
Label::new(RichText::new(&self.message).color(Color32::BLACK)).wrap(),
);
ui.add_space(ui.available_width());
label_resp
}
})
.inner
})
.inner
}
}
pub fn alert(level: AlertLevel, message: &str) -> Alert {
Alert::new(message).with_level(level)
}