catppuccin_egui/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
//! Soothing pastel theme for [egui](egui).
//!
//! To use, call [`set_theme`](crate::set_theme) with the egui context
//! and a [`Theme`](crate::Theme).
//!
//! # Example
//!
//! ```rust
//! # use eframe::egui;
//! struct App;
//! impl eframe::App for App {
//! fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
//! catppuccin_egui::set_theme(ctx, catppuccin_egui::MACCHIATO);
//! egui::CentralPanel::default().show(&ctx, |ui| {
//! ui.label("Hello, world!");
//! });
//! }
//! }
//! ```
//!
//! You can also customize your own theme:
//!
//! ```rust
//! # use eframe::egui;
//! use catppuccin_egui::{Theme, MOCHA};
//! const MY_MOCHA: Theme = Theme {
//! red: egui::Color32::from_rgb(255, 0, 0),
//! ..MOCHA
//! };
//! ```
//!
#[cfg(not(any(
feature = "egui26",
feature = "egui27",
feature = "egui28",
feature = "egui29"
)))]
compile_error!("at least one egui version must be enabled");
#[cfg(feature = "egui26")]
use egui26 as egui;
#[cfg(feature = "egui27")]
use egui27 as egui;
#[cfg(feature = "egui28")]
use egui28 as egui;
#[cfg(feature = "egui29")]
use egui29 as egui;
use egui::{epaint, style};
mod themes;
pub use themes::*;
/// Apply the given theme to a [`Context`](egui::Context).
pub fn set_theme(ctx: &egui::Context, theme: Theme) {
let old = ctx.style().visuals.clone();
ctx.set_visuals(theme.visuals(old));
}
/// Apply the given theme to a [`Style`](egui::Style).
///
/// # Example
///
/// ```rust
/// # use eframe::egui;
/// # use egui::__run_test_ctx;
/// # __run_test_ctx(|ctx| {
/// let mut style = (*ctx.style()).clone();
/// catppuccin_egui::set_style_theme(&mut style, catppuccin_egui::MACCHIATO);
/// ctx.set_style(style);
/// # });
/// ```
pub fn set_style_theme(style: &mut egui::Style, theme: Theme) {
let old = style.visuals.clone();
style.visuals = theme.visuals(old);
}
fn make_widget_visual(
old: style::WidgetVisuals,
theme: &Theme,
bg_fill: egui::Color32,
) -> style::WidgetVisuals {
style::WidgetVisuals {
bg_fill,
weak_bg_fill: bg_fill,
bg_stroke: egui::Stroke {
color: theme.overlay1,
..old.bg_stroke
},
fg_stroke: egui::Stroke {
color: theme.text,
..old.fg_stroke
},
..old
}
}
impl Theme {
fn visuals(&self, old: egui::Visuals) -> egui::Visuals {
let is_latte = *self == LATTE;
egui::Visuals {
override_text_color: Some(self.text),
hyperlink_color: self.rosewater,
faint_bg_color: self.surface0,
extreme_bg_color: self.crust,
code_bg_color: self.mantle,
warn_fg_color: self.peach,
error_fg_color: self.maroon,
window_fill: self.base,
panel_fill: self.base,
window_stroke: egui::Stroke {
color: self.overlay1,
..old.window_stroke
},
widgets: style::Widgets {
noninteractive: make_widget_visual(old.widgets.noninteractive, self, self.base),
inactive: make_widget_visual(old.widgets.inactive, self, self.surface0),
hovered: make_widget_visual(old.widgets.hovered, self, self.surface2),
active: make_widget_visual(old.widgets.active, self, self.surface1),
open: make_widget_visual(old.widgets.open, self, self.surface0),
},
selection: style::Selection {
bg_fill: self.blue.linear_multiply(if is_latte { 0.4 } else { 0.2 }),
stroke: egui::Stroke {
color: self.overlay1,
..old.selection.stroke
},
},
window_shadow: epaint::Shadow {
color: self.base,
..old.window_shadow
},
popup_shadow: epaint::Shadow {
color: self.base,
..old.popup_shadow
},
dark_mode: !is_latte,
..old
}
}
}