Skip to content

Commit

Permalink
Merge pull request #27 from urholaukkarinen/custom-style
Browse files Browse the repository at this point in the history
The default toast style can be customized
  • Loading branch information
urholaukkarinen authored Jul 14, 2024
2 parents e85c698 + 488f4fd commit bb73d91
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 35 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ if ui.button("Add toast").clicked() {
kind: ToastKind::Error,
options: ToastOptions::default()
.duration_in_seconds(5.0)
.show_progress(true)
.show_progress(true),
..Default::default()
});
}

Expand All @@ -41,7 +42,7 @@ toasts.show(ctx);
## Customization

Look of the notifications can be fully customized.

```rust
const MY_CUSTOM_TOAST: u32 = 0;

Expand All @@ -66,7 +67,8 @@ if ui.button("Add toast").clicked() {
toasts.add(Toast {
text: "Hello, World!".into(),
kind: ToastKind::Custom(MY_CUSTOM_TOAST),
options: ToastOptions::default()
options: ToastOptions::default(),
..Default::default()
});
}

Expand Down
28 changes: 17 additions & 11 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use eframe::egui;
use eframe::epaint::Margin;
use egui::{Align2, Color32, Direction, Frame, Pos2, RichText, Widget};

use egui_toast::{Toast, ToastKind, ToastOptions, Toasts};
use egui_toast::{Toast, ToastKind, ToastOptions, ToastStyle, Toasts};

/// Identifier for a custom toast kind
const MY_CUSTOM_TOAST: u32 = 0;
Expand Down Expand Up @@ -169,22 +169,28 @@ impl Demo {
.show_progress(*show_progress)
.duration(duration);

let style = ToastStyle::default();

if ui.button("Give me a toast").clicked() {
toasts.add(Toast {
kind: *kind,
text: format!("Hello, I am a toast {}", i).into(),
options,
});
toasts.add(
Toast::default()
.kind(*kind)
.text(format!("Hello, I am a toast {}", i))
.options(options)
.style(style.clone()),
);

*i += 1;
}

if ui.button("Give me a custom toast").clicked() {
toasts.add(Toast {
text: format!("Hello, I am a custom toast {}", i).into(),
kind: ToastKind::Custom(MY_CUSTOM_TOAST),
options,
});
toasts.add(
Toast::default()
.kind(ToastKind::Custom(MY_CUSTOM_TOAST))
.text(format!("Hello, I am a custom toast {}", i))
.options(options)
.style(style.clone()),
);

*i += 1;
}
Expand Down
28 changes: 11 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
//! options: ToastOptions::default()
//! .duration_in_seconds(3.0)
//! .show_progress(true)
//! .show_icon(true)
//! .show_icon(true),
//! ..Default::default()
//! });
//!
Expand Down Expand Up @@ -56,6 +57,7 @@
//! text: "Hello, World".into(),
//! kind: ToastKind::Custom(MY_CUSTOM_TOAST),
//! options: ToastOptions::default(),
//! ..Default::default()
//! });
//!
//! # })
Expand All @@ -72,15 +74,9 @@ use std::time::Duration;

use egui::epaint::RectShape;
use egui::{
Align2, Area, Color32, Context, Direction, Frame, Id, Order, Pos2, Response, RichText,
Rounding, Shape, Stroke, Ui,
Align2, Area, Context, Direction, Frame, Id, Order, Pos2, Response, Rounding, Shape, Stroke, Ui,
};

pub const INFO_COLOR: Color32 = Color32::from_rgb(0, 155, 255);
pub const WARNING_COLOR: Color32 = Color32::from_rgb(255, 212, 0);
pub const ERROR_COLOR: Color32 = Color32::from_rgb(255, 32, 0);
pub const SUCCESS_COLOR: Color32 = Color32::from_rgb(0, 255, 32);

pub type ToastContents = dyn Fn(&mut Ui, &mut Toast) -> Response + Send + Sync;

pub struct Toasts {
Expand Down Expand Up @@ -225,21 +221,19 @@ fn default_toast_contents(ui: &mut Ui, toast: &mut Toast) -> Response {
.stroke(Stroke::NONE)
.show(ui, |ui| {
ui.horizontal(|ui| {
let (icon, color) = match toast.kind {
ToastKind::Warning => ("⚠", WARNING_COLOR),
ToastKind::Error => ("❗", ERROR_COLOR),
ToastKind::Success => ("✔", SUCCESS_COLOR),
_ => ("ℹ", INFO_COLOR),
};

let a = |ui: &mut Ui, toast: &mut Toast| {
if toast.options.show_icon {
ui.label(RichText::new(icon).color(color));
ui.label(match toast.kind {
ToastKind::Warning => toast.style.warning_icon.clone(),
ToastKind::Error => toast.style.error_icon.clone(),
ToastKind::Success => toast.style.success_icon.clone(),
_ => toast.style.info_icon.clone(),
});
}
};
let b = |ui: &mut Ui, toast: &mut Toast| ui.label(toast.text.clone());
let c = |ui: &mut Ui, toast: &mut Toast| {
if ui.button("🗙").clicked() {
if ui.button(toast.style.close_button_text.clone()).clicked() {
toast.close();
}
};
Expand Down
55 changes: 51 additions & 4 deletions src/toast.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use egui::WidgetText;
use egui::{Color32, WidgetText};
use std::time::Duration;

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[derive(Default, Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum ToastKind {
#[default]
Info,
Warning,
Error,
Expand All @@ -16,21 +17,67 @@ impl From<u32> for ToastKind {
}
}

#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Toast {
pub kind: ToastKind,
pub text: WidgetText,
pub options: ToastOptions,
pub style: ToastStyle,
}

impl Toast {
pub fn new() -> Self {
Self::default()
}

pub fn kind(mut self, kind: ToastKind) -> Self {
self.kind = kind;
self
}

pub fn text(mut self, text: impl Into<WidgetText>) -> Self {
self.text = text.into();
self
}

pub fn options(mut self, options: ToastOptions) -> Self {
self.options = options;
self
}

pub fn style(mut self, style: ToastStyle) -> Self {
self.style = style;
self
}

/// Close the toast immediately
pub fn close(&mut self) {
self.options.ttl_sec = 0.0;
}
}

#[derive(Copy, Clone)]
#[derive(Clone)]
pub struct ToastStyle {
pub info_icon: WidgetText,
pub warning_icon: WidgetText,
pub error_icon: WidgetText,
pub success_icon: WidgetText,
pub close_button_text: WidgetText,
}

impl Default for ToastStyle {
fn default() -> Self {
Self {
info_icon: WidgetText::from("ℹ").color(Color32::from_rgb(0, 155, 255)),
warning_icon: WidgetText::from("⚠").color(Color32::from_rgb(255, 212, 0)),
error_icon: WidgetText::from("❗").color(Color32::from_rgb(255, 32, 0)),
success_icon: WidgetText::from("✔").color(Color32::from_rgb(0, 255, 32)),
close_button_text: WidgetText::from("🗙"),
}
}
}

#[derive(Debug, Copy, Clone)]
pub struct ToastOptions {
/// Whether the toast should include an icon.
pub show_icon: bool,
Expand Down

0 comments on commit bb73d91

Please sign in to comment.