use crate::properties::{Property, color, size, display, font, border, position, layout, flex, grid, transition, size_ext};
use crate::values::*;
use std::fmt;
#[derive(Debug, Default)]
pub struct Style {
properties: Vec<Property>,
}
impl Style {
pub fn new() -> Self {
Self {
properties: Vec::new(),
}
}
pub fn add_property(&mut self, property: Property) -> &mut Self {
self.properties.push(property);
self
}
pub fn apply(&self) -> String {
self.to_string()
}
pub fn build(&self) -> String {
self.apply()
}
pub fn custom_property<T: fmt::Display>(&mut self, name: &str, value: T) -> &mut Self {
self.add_property(Property::new(name, value))
}
pub fn set_var<T: fmt::Display>(&mut self, name: &str, value: T) -> &mut Self {
let var_name = if name.trim().starts_with("--") {
name.trim().to_string()
} else {
format!("--{}", name.trim())
};
self.custom_property(&var_name, value)
}
pub fn color(&mut self, value: Color) -> &mut Self {
self.add_property(color::color(value))
}
pub fn background_color(&mut self, value: Color) -> &mut Self {
self.add_property(color::background_color(value))
}
pub fn border_color(&mut self, value: Color) -> &mut Self {
self.add_property(color::border_color(value))
}
pub fn width(&mut self, value: Size) -> &mut Self {
self.add_property(size::width(value))
}
pub fn height(&mut self, value: Size) -> &mut Self {
self.add_property(size::height(value))
}
pub fn margin(&mut self, value: Size) -> &mut Self {
self.add_property(size::margin(value))
}
pub fn margin_top(&mut self, value: Size) -> &mut Self {
self.add_property(size::margin_top(value))
}
pub fn margin_right(&mut self, value: Size) -> &mut Self {
self.add_property(size::margin_right(value))
}
pub fn margin_bottom(&mut self, value: Size) -> &mut Self {
self.add_property(size::margin_bottom(value))
}
pub fn margin_left(&mut self, value: Size) -> &mut Self {
self.add_property(size::margin_left(value))
}
pub fn padding(&mut self, value: Size) -> &mut Self {
self.add_property(size::padding(value))
}
pub fn padding_top(&mut self, value: Size) -> &mut Self {
self.add_property(size::padding_top(value))
}
pub fn padding_right(&mut self, value: Size) -> &mut Self {
self.add_property(size::padding_right(value))
}
pub fn padding_bottom(&mut self, value: Size) -> &mut Self {
self.add_property(size::padding_bottom(value))
}
pub fn padding_left(&mut self, value: Size) -> &mut Self {
self.add_property(size::padding_left(value))
}
pub fn font_size(&mut self, value: Size) -> &mut Self {
self.add_property(size::font_size(value))
}
pub fn line_height(&mut self, value: Size) -> &mut Self {
self.add_property(size::line_height(value))
}
pub fn border_width(&mut self, value: Size) -> &mut Self {
self.add_property(size::border_width(value))
}
pub fn display(&mut self, value: Display) -> &mut Self {
self.add_property(display::display(value))
}
pub fn position(&mut self, value: Position) -> &mut Self {
self.add_property(display::position(value))
}
pub fn flex_direction(&mut self, value: FlexDirection) -> &mut Self {
self.add_property(display::flex_direction(value))
}
pub fn justify_content(&mut self, value: JustifyContent) -> &mut Self {
self.add_property(display::justify_content(value))
}
pub fn align_items(&mut self, value: AlignItems) -> &mut Self {
self.add_property(display::align_items(value))
}
pub fn font_weight(&mut self, value: FontWeight) -> &mut Self {
self.add_property(font::font_weight(value))
}
pub fn font_family(&mut self, value: &str) -> &mut Self {
self.add_property(font::font_family(value))
}
pub fn text_align(&mut self, value: TextAlign) -> &mut Self {
self.add_property(font::text_align(value))
}
pub fn font_size_enum(&mut self, value: FontSize) -> &mut Self {
self.add_property(font::font_size_enum(value))
}
pub fn line_height_enum(&mut self, value: LineHeight) -> &mut Self {
self.add_property(font::line_height_enum(value))
}
pub fn text_decoration(&mut self, value: TextDecoration) -> &mut Self {
self.add_property(font::text_decoration(value))
}
pub fn border_style(&mut self, value: BorderStyle) -> &mut Self {
self.add_property(border::border_style(value))
}
pub fn border_radius(&mut self, value: Size) -> &mut Self {
self.add_property(border::border_radius(value))
}
pub fn border(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
self.add_property(border::border(width, style, color))
}
pub fn border_top(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
self.add_property(border::border_top(width, style, color))
}
pub fn border_right(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
self.add_property(border::border_right(width, style, color))
}
pub fn border_bottom(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
self.add_property(border::border_bottom(width, style, color))
}
pub fn border_left(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
self.add_property(border::border_left(width, style, color))
}
pub fn box_shadow(&mut self, value: BoxShadow) -> &mut Self {
self.add_property(border::box_shadow(value))
}
pub fn box_shadow_none(&mut self) -> &mut Self {
self.add_property(border::box_shadow_none())
}
pub fn top(&mut self, value: Size) -> &mut Self {
self.add_property(position::top(value))
}
pub fn right(&mut self, value: Size) -> &mut Self {
self.add_property(position::right(value))
}
pub fn bottom(&mut self, value: Size) -> &mut Self {
self.add_property(position::bottom(value))
}
pub fn left(&mut self, value: Size) -> &mut Self {
self.add_property(position::left(value))
}
pub fn z_index(&mut self, value: ZIndex) -> &mut Self {
self.add_property(position::z_index(value))
}
pub fn overflow(&mut self, value: Overflow) -> &mut Self {
self.add_property(layout::overflow(value))
}
pub fn overflow_x(&mut self, value: Overflow) -> &mut Self {
self.add_property(layout::overflow_x(value))
}
pub fn overflow_y(&mut self, value: Overflow) -> &mut Self {
self.add_property(layout::overflow_y(value))
}
pub fn visibility(&mut self, value: Visibility) -> &mut Self {
self.add_property(layout::visibility(value))
}
pub fn opacity(&mut self, value: f32) -> &mut Self {
self.add_property(layout::opacity(value))
}
pub fn cursor(&mut self, value: Cursor) -> &mut Self {
self.add_property(layout::cursor(value))
}
pub fn gap(&mut self, value: Size) -> &mut Self {
self.add_property(flex::gap(value))
}
pub fn row_gap(&mut self, value: Size) -> &mut Self {
self.add_property(flex::row_gap(value))
}
pub fn column_gap(&mut self, value: Size) -> &mut Self {
self.add_property(flex::column_gap(value))
}
pub fn grid_template_columns(&mut self, value: &str) -> &mut Self {
self.add_property(grid::grid_template_columns(value))
}
pub fn grid_template_rows(&mut self, value: &str) -> &mut Self {
self.add_property(grid::grid_template_rows(value))
}
pub fn transition(&mut self, value: Transition) -> &mut Self {
self.add_property(transition::transition(value))
}
pub fn transition_none(&mut self) -> &mut Self {
self.add_property(transition::transition_none())
}
pub fn transition_all(&mut self, duration: f32, timing_function: Option<&str>, delay: Option<f32>) -> &mut Self {
self.add_property(transition::transition_all(duration, timing_function, delay))
}
pub fn max_width(&mut self, value: Size) -> &mut Self {
self.add_property(size_ext::max_width(value))
}
pub fn min_width(&mut self, value: Size) -> &mut Self {
self.add_property(size_ext::min_width(value))
}
pub fn max_height(&mut self, value: Size) -> &mut Self {
self.add_property(size_ext::max_height(value))
}
pub fn min_height(&mut self, value: Size) -> &mut Self {
self.add_property(size_ext::min_height(value))
}
}
impl fmt::Display for Style {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, property) in self.properties.iter().enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{}", property)?;
}
Ok(())
}
}
pub fn style() -> Style {
Style::new()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_style_builder() {
let css = style()
.color(Color::White)
.background_color(Color::Rgba(255, 0, 0, 0.5))
.font_size(Size::Px(16))
.display(Display::Flex)
.apply();
assert_eq!(
css,
"color: white; background-color: rgba(255, 0, 0, 0.5); font-size: 16px; display: flex;"
);
}
#[test]
fn test_empty_style() {
let css = style().apply();
assert_eq!(css, "");
}
#[test]
fn test_multiple_properties() {
let css = style()
.width(Size::Percent(100.0))
.height(Size::Px(200))
.margin(Size::Auto)
.padding(Size::Px(10))
.apply();
assert_eq!(
css,
"width: 100%; height: 200px; margin: auto; padding: 10px;"
);
}
}