bevy_pf 0.1.0

A XAML / WPF-like UI framework for Bevy: XAML in macros or files, styling with resources, and the common WPF control set.
Documentation
//! Built-in themes: popular palettes as swappable resource dictionaries.
//!
//! Every theme defines the same `Pf.*` brush keys plus implicit styles that
//! reference them through `{DynamicResource}`, so applying another theme
//! re-colors a live UI in place (the deferred-resource system refreshes every
//! reference on the app-resources revision bump).
//!
//! ```ignore
//! bevy_pf::themes::apply_theme(world, "catppuccin-mocha").unwrap();
//! ```

use bevy::prelude::*;

use crate::XamlEnv;
use crate::error::PfError;

/// A built-in theme.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ThemeInfo {
    pub slug: &'static str,
    pub name: &'static str,
    pub dark: bool,
}

/// Every built-in theme, in menu order.
pub const THEMES: &[ThemeInfo] = &[
    ThemeInfo { slug: "fluent-light", name: "Fluent Light", dark: false },
    ThemeInfo { slug: "fluent-dark", name: "Fluent Dark", dark: true },
    ThemeInfo { slug: "material-light", name: "Material Light", dark: false },
    ThemeInfo { slug: "material-dark", name: "Material Dark", dark: true },
    ThemeInfo { slug: "nord", name: "Nord", dark: true },
    ThemeInfo { slug: "dracula", name: "Dracula", dark: true },
    ThemeInfo { slug: "catppuccin-latte", name: "Catppuccin Latte", dark: false },
    ThemeInfo { slug: "catppuccin-mocha", name: "Catppuccin Mocha", dark: true },
    ThemeInfo { slug: "solarized-light", name: "Solarized Light", dark: false },
    ThemeInfo { slug: "solarized-dark", name: "Solarized Dark", dark: true },
    ThemeInfo { slug: "gruvbox-dark", name: "Gruvbox Dark", dark: true },
    ThemeInfo { slug: "tokyo-night", name: "Tokyo Night", dark: true },
];

/// The XAML source of a built-in theme dictionary.
pub fn theme_source(slug: &str) -> Option<&'static str> {
    match slug {
        "fluent-light" => Some(include_str!("../assets/themes/fluent-light.xaml")),
        "fluent-dark" => Some(include_str!("../assets/themes/fluent-dark.xaml")),
        "material-light" => Some(include_str!("../assets/themes/material-light.xaml")),
        "material-dark" => Some(include_str!("../assets/themes/material-dark.xaml")),
        "nord" => Some(include_str!("../assets/themes/nord.xaml")),
        "dracula" => Some(include_str!("../assets/themes/dracula.xaml")),
        "catppuccin-latte" => Some(include_str!("../assets/themes/catppuccin-latte.xaml")),
        "catppuccin-mocha" => Some(include_str!("../assets/themes/catppuccin-mocha.xaml")),
        "solarized-light" => Some(include_str!("../assets/themes/solarized-light.xaml")),
        "solarized-dark" => Some(include_str!("../assets/themes/solarized-dark.xaml")),
        "gruvbox-dark" => Some(include_str!("../assets/themes/gruvbox-dark.xaml")),
        "tokyo-night" => Some(include_str!("../assets/themes/tokyo-night.xaml")),
        _ => None,
    }
}

/// Parse a built-in theme and merge it into the application resources.
/// Returns instantiation warnings (empty on the built-ins).
pub fn apply_theme(world: &mut World, slug: &str) -> Result<Vec<String>, PfError> {
    let source = theme_source(slug)
        .ok_or_else(|| PfError::instantiate(format!("unknown theme `{slug}`")))?;
    let doc = bevy_pf_xaml::parse(source)?;
    Ok(crate::instantiate::set_application_resources(
        world,
        &doc,
        &XamlEnv::default(),
    ))
}