bevy_ui_styled_macros 0.4.0

Macros for bevy_ui_styled
Documentation
use std::fmt::Debug;

use bevy::{
    prelude::Color,
    ui::{Overflow, Style, UiRect, Val},
};
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};

pub(crate) fn quote_color_rgba(color: Color) -> TokenStream {
    let [r, g, b, a] = color.as_rgba_f32();
    quote!(bevy::prelude::Color::rgba(#r, #g, #b, #a))
}

pub(crate) fn quote_style(style: Style) -> TokenStream {
    let display = quote_enum(style.display);
    let position_type = quote_enum(style.position_type);
    let direction = quote_enum(style.direction);
    let flex_direction = quote_enum(style.flex_direction);
    let flex_wrap = quote_enum(style.flex_wrap);

    let align_items = quote_enum(style.align_items);
    let justify_items = quote_enum(style.justify_items);

    let align_self = quote_enum(style.align_self);
    let justify_self = quote_enum(style.justify_self);

    let align_content = quote_enum(style.align_content);
    let justify_content = quote_enum(style.justify_content);

    let left = quote_val(style.left);
    let right = quote_val(style.right);
    let top = quote_val(style.top);
    let bottom = quote_val(style.bottom);

    let width = quote_val(style.width);
    let height = quote_val(style.height);

    let max_width = quote_val(style.max_width);
    let max_height = quote_val(style.max_height);

    let min_width = quote_val(style.min_width);
    let min_height = quote_val(style.min_height);

    let margin = quote_ui_rect(style.margin);
    let padding = quote_ui_rect(style.padding);
    let border = quote_ui_rect(style.border);
    let flex_grow = quote_f32(style.flex_grow);
    let flex_shrink = quote_f32(style.flex_shrink);
    let flex_basis = quote_val(style.flex_basis);
    let aspect_ratio = quote_option(style.aspect_ratio);
    let overflow = quote_ui_overflow(style.overflow);
    let row_gap = quote_val(style.row_gap);
    let column_gap = quote_val(style.column_gap);

    let grid_auto_flow = quote_enum(style.grid_auto_flow);

    quote! {
        bevy::ui::Style {
            display: #display,
            position_type: #position_type,
            left: #left,
            right: #right,
            top: #top,
            bottom: #bottom,
            direction: #direction,
            flex_direction: #flex_direction,
            flex_wrap: #flex_wrap,
            align_items: #align_items,
            justify_items: #justify_items,
            align_self: #align_self,
            justify_self: #justify_self,
            align_content: #align_content,
            justify_content: #justify_content,
            margin: #margin,
            padding: #padding,
            border: #border,
            flex_grow: #flex_grow,
            flex_shrink: #flex_shrink,
            flex_basis: #flex_basis,
            width: #width,
            height: #height,
            min_width: #min_width,
            min_height: #min_height,
            max_width: #max_width,
            max_height: #max_height,
            aspect_ratio: #aspect_ratio,
            overflow: #overflow,
            row_gap: #row_gap,
            column_gap: #column_gap,
            grid_auto_flow: #grid_auto_flow,
            grid_template_rows: std::vec::Vec::new(),
            grid_template_columns: std::vec::Vec::new(),
            grid_auto_rows: std::vec::Vec::new(),
            grid_auto_columns: std::vec::Vec::new(),
            grid_row: bevy::ui::GridPlacement::default(),
            grid_column: bevy::ui::GridPlacement::default(),
        }
    }
}

pub fn quote_option<T: ToTokens>(opt: Option<T>) -> TokenStream {
    match opt {
        Some(value) => quote!(Some(#value)),
        None => quote!(None),
    }
}

fn quote_enum<T: Debug>(value: T) -> TokenStream {
    let type_name = std::any::type_name::<T>().to_string();
    let type_name = type_name.split("::").last().unwrap();
    let type_name: proc_macro2::TokenStream = type_name.parse().unwrap();
    let value: proc_macro2::TokenStream = format!("{:?}", value).parse().unwrap();
    quote!(bevy::ui::#type_name::#value)
}

fn quote_f32(value: f32) -> TokenStream {
    quote!(#value)
}

fn quote_val(val: Val) -> TokenStream {
    let value: proc_macro2::TokenStream = format!("{:?}", val).parse().unwrap();
    quote!(bevy::ui::Val::#value)
}

fn quote_ui_rect(rect: UiRect) -> TokenStream {
    let left = quote_val(rect.left);
    let right = quote_val(rect.right);
    let top = quote_val(rect.top);
    let bottom = quote_val(rect.bottom);
    quote!(bevy::ui::UiRect {
        left: #left,
        right: #right,
        top: #top,
        bottom: #bottom,
    })
}

fn quote_ui_overflow(overflow: Overflow) -> TokenStream {
    let x = quote_enum(overflow.x);
    let y = quote_enum(overflow.y);
    quote!(bevy::ui::Overflow {
        x: #x,
        y: #y,
    })
}