use egui::{Context, Id};
use std::any::TypeId;
use crate::theme::StyledTheme;
fn slot_id() -> Id {
Id::new("egui_styled::design_slot")
}
pub trait DesignSlots {
fn set_design_data<T: 'static + Clone + Send + Sync>(&self, value: T);
fn design_data<T: 'static + Clone + Send + Sync + Default>(&self) -> T;
fn design<T: 'static + Clone + Send + Sync + Default>(&self) -> (StyledTheme, T) {
(self.design_data::<StyledTheme>(), self.design_data::<T>())
}
}
impl DesignSlots for Context {
fn set_design_data<T: 'static + Clone + Send + Sync>(&self, value: T) {
let _ = TypeId::of::<T>(); self.memory_mut(|mem| mem.data.insert_temp(slot_id(), value));
}
fn design_data<T: 'static + Clone + Send + Sync + Default>(&self) -> T {
self.memory_mut(|mem| mem.data.get_temp::<T>(slot_id()).unwrap_or_default())
}
}
pub trait ThemeExt {
fn set_styled_theme(&self, theme: StyledTheme);
fn styled_theme(&self) -> StyledTheme;
}
impl ThemeExt for Context {
fn set_styled_theme(&self, theme: StyledTheme) {
self.set_design_data(theme);
}
fn styled_theme(&self) -> StyledTheme {
self.design_data::<StyledTheme>()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Clone, Default, PartialEq, Debug)]
struct FooColors {
accent: u32,
}
#[derive(Clone, Default, PartialEq, Debug)]
struct BarColors {
accent: u32,
}
#[test]
fn design_slot_roundtrip() {
let ctx = Context::default();
ctx.set_design_data(FooColors { accent: 42 });
assert_eq!(ctx.design_data::<FooColors>().accent, 42);
}
#[test]
fn different_types_dont_collide() {
let ctx = Context::default();
ctx.set_design_data(FooColors { accent: 1 });
ctx.set_design_data(BarColors { accent: 2 });
assert_eq!(ctx.design_data::<FooColors>().accent, 1);
assert_eq!(ctx.design_data::<BarColors>().accent, 2);
}
#[test]
fn unset_type_returns_default() {
let ctx = Context::default();
assert_eq!(ctx.design_data::<FooColors>(), FooColors::default());
}
#[test]
fn theme_ext_still_works() {
let ctx = Context::default();
ctx.set_styled_theme(StyledTheme::default());
let _ = ctx.styled_theme();
}
}