use crate::view::style::{Align, Direction, Justify, Length, Overflow, ShadowPreset, Shadows, Style};
use crate::view::theme::ColorSpec;
use crate::core::{Pixels, px};
macro_rules! constant_setters {
($($name:ident => $field:ident = $value:expr;)*) => {
$(
fn $name(mut self) -> Self {
self.style().$field = Some($value);
self
}
)*
};
}
macro_rules! length_setters {
($($name:ident => $field:ident;)*) => {
$(
fn $name(mut self, value: Pixels) -> Self {
self.style().$field = Some(Length::Px(value));
self
}
)*
};
}
macro_rules! scale_methods {
($prefix:ident, $apply:expr; $($step:literal),*) => {
paste::paste! {
$(
fn [<$prefix _ $step>](mut self) -> Self {
let apply: fn(&mut Style, Pixels) = $apply;
apply(self.style(), px($step as f32 * 4.0));
self
}
)*
}
};
}
pub trait Styled: Sized {
fn style(&mut self) -> &mut Style;
fn flex(self) -> Self {
self
}
constant_setters! {
flex_row => direction = Direction::Row;
flex_col => direction = Direction::Column;
flex_wrap => wrap = true;
flex_grow => flex_grow = 1.0;
flex_shrink_0 => flex_shrink = 0.0;
items_start => align_items = Align::Start;
items_center => align_items = Align::Center;
items_end => align_items = Align::End;
justify_start => justify_content = Justify::Start;
justify_center => justify_content = Justify::Center;
justify_end => justify_content = Justify::End;
justify_between => justify_content = Justify::SpaceBetween;
absolute => absolute = true;
hidden => hidden = true;
w_full => width = Length::Percent(1.0);
h_full => height = Length::Percent(1.0);
rounded_none => radius = Pixels::ZERO;
rounded_sm => radius = px(2.0);
rounded_md => radius = px(6.0);
rounded_lg => radius = px(8.0);
rounded_xl => radius = px(12.0);
rounded_full => radius = px(9999.0);
border_1 => border_width = px(1.0);
border_2 => border_width = px(2.0);
text_xs => font_size = px(12.0);
text_sm => font_size = px(13.0);
text_base => font_size = px(14.0);
text_lg => font_size = px(18.0);
shadow_none => shadow = Shadows::NONE;
shadow_xs => shadow = ShadowPreset::Xs.shadows();
shadow_sm => shadow = ShadowPreset::Sm.shadows();
shadow_md => shadow = ShadowPreset::Md.shadows();
shadow_lg => shadow = ShadowPreset::Lg.shadows();
shadow_xl => shadow = ShadowPreset::Xl.shadows();
shadow_2xl => shadow = ShadowPreset::Xxl.shadows();
overflow_y_scroll => overflow_y = Overflow::Scroll;
font_bold => font_bold = true;
italic => italic = true;
underline => underline = true;
whitespace_nowrap => text_wrap = false;
whitespace_normal => text_wrap = true;
text_2xl => font_size = px(24.0);
}
fn flex_1(mut self) -> Self {
let style = self.style();
style.flex_grow = Some(1.0);
style.flex_shrink = Some(1.0);
style.flex_basis = Some(Length::Px(Pixels::ZERO));
self
}
length_setters! {
w => width;
h => height;
min_w => min_width;
min_h => min_height;
max_w => max_width;
max_h => max_height;
}
fn aspect_ratio(mut self, ratio: f32) -> Self {
self.style().aspect_ratio = Some(ratio);
self
}
fn size(self, side: Pixels) -> Self {
self.w(side).h(side)
}
fn size_full(self) -> Self {
self.w_full().h_full()
}
fn px(mut self, value: Pixels) -> Self {
self.style().padding.set_horizontal(value);
self
}
fn py(mut self, value: Pixels) -> Self {
self.style().padding.set_vertical(value);
self
}
fn m(mut self, value: Pixels) -> Self {
self.style().margin.set_all(value);
self
}
fn pl(mut self, value: Pixels) -> Self {
self.style().padding.left = Some(value);
self
}
fn pr(mut self, value: Pixels) -> Self {
self.style().padding.right = Some(value);
self
}
fn pt(mut self, value: Pixels) -> Self {
self.style().padding.top = Some(value);
self
}
fn pb(mut self, value: Pixels) -> Self {
self.style().padding.bottom = Some(value);
self
}
fn mt(mut self, value: Pixels) -> Self {
self.style().margin.top = Some(value);
self
}
fn ml(mut self, value: Pixels) -> Self {
self.style().margin.left = Some(value);
self
}
fn gap(mut self, value: Pixels) -> Self {
let style = self.style();
style.gap_x = Some(value);
style.gap_y = Some(value);
self
}
scale_methods!(p, |style, value| style.padding.set_all(value); 0, 1, 2, 3, 4, 5, 6, 8);
scale_methods!(px, |style, value| style.padding.set_horizontal(value); 1, 2, 3, 4, 6, 8);
scale_methods!(py, |style, value| style.padding.set_vertical(value); 1, 2, 3, 4, 6, 8);
scale_methods!(m, |style, value| style.margin.set_all(value); 1, 2, 3, 4, 6, 8);
scale_methods!(mx, |style, value| style.margin.set_horizontal(value); 1, 2, 3, 4, 6, 8);
scale_methods!(my, |style, value| style.margin.set_vertical(value); 1, 2, 3, 4, 6, 8);
scale_methods!(mt, |style, value| style.margin.top = Some(value); 1, 2, 3, 4, 6, 8);
scale_methods!(mb, |style, value| style.margin.bottom = Some(value); 1, 2, 3, 4, 6, 8);
scale_methods!(pt, |style, value| style.padding.top = Some(value); 1, 2, 3, 4, 6, 8);
scale_methods!(pb, |style, value| style.padding.bottom = Some(value); 1, 2, 3, 4, 6, 8);
scale_methods!(pl, |style, value| style.padding.left = Some(value); 1, 2, 3, 4, 6, 8);
scale_methods!(pr, |style, value| style.padding.right = Some(value); 1, 2, 3, 4, 6, 8);
scale_methods!(gap, |style, value| { style.gap_x = Some(value); style.gap_y = Some(value); }; 1, 2, 3, 4, 6, 8);
scale_methods!(w, |style, value| style.width = Some(Length::Px(value)); 4, 8, 16, 32, 48, 64, 72);
scale_methods!(h, |style, value| style.height = Some(Length::Px(value)); 4, 5, 6, 7, 8, 9, 10);
fn inset_0(mut self) -> Self {
self.style().inset.set_all(Pixels::ZERO);
self
}
fn top(mut self, value: Pixels) -> Self {
self.style().inset.top = Some(value);
self
}
fn right(mut self, value: Pixels) -> Self {
self.style().inset.right = Some(value);
self
}
fn bottom(mut self, value: Pixels) -> Self {
self.style().inset.bottom = Some(value);
self
}
fn left(mut self, value: Pixels) -> Self {
self.style().inset.left = Some(value);
self
}
fn shadow(mut self, shadow: impl Into<Shadows>) -> Self {
self.style().shadow = Some(shadow.into());
self
}
fn shadow_color(mut self, color: impl Into<ColorSpec>) -> Self {
let current = self.style().shadow.unwrap_or(ShadowPreset::Md.shadows());
self.style().shadow = Some(current.tinted(color.into()));
self
}
fn glow(self, color: impl Into<ColorSpec>, blur: f32) -> Self {
self.shadow(crate::view::style::BoxShadow::new(0.0, 0.0, blur).color(color))
}
fn border_color(mut self, color: impl Into<ColorSpec>) -> Self {
self.style().border_color = Some(color.into());
self
}
fn bg_gradient(mut self, angle: f32, from: impl Into<ColorSpec>, to: impl Into<ColorSpec>) -> Self {
self.style().background = Some(from.into());
self.style().gradient = Some((angle, to.into()));
self
}
fn bg(mut self, color: impl Into<ColorSpec>) -> Self {
self.style().background = Some(color.into());
self
}
fn text_color(mut self, color: impl Into<ColorSpec>) -> Self {
self.style().text_color = Some(color.into());
self
}
fn text_size(mut self, size: Pixels) -> Self {
self.style().font_size = Some(size);
self
}
fn opacity(mut self, value: f32) -> Self {
self.style().opacity = Some(value);
self
}
fn overflow_hidden(mut self) -> Self {
let style = self.style();
style.overflow_x = Some(Overflow::Hidden);
style.overflow_y = Some(Overflow::Hidden);
self
}
}
impl Styled for Style {
fn style(&mut self) -> &mut Style {
self
}
}