use crate::{bindings::*, Declaration};
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum SizingType {
Fit = Clay__SizingType_CLAY__SIZING_TYPE_FIT,
Grow = Clay__SizingType_CLAY__SIZING_TYPE_GROW,
Percent = Clay__SizingType_CLAY__SIZING_TYPE_PERCENT,
Fixed = Clay__SizingType_CLAY__SIZING_TYPE_FIXED,
}
#[derive(Debug, Clone, Copy)]
pub enum Sizing {
Fit(f32, f32),
Grow(f32, f32),
Fixed(f32),
Percent(f32),
}
impl From<Sizing> for Clay_SizingAxis {
fn from(value: Sizing) -> Self {
match value {
Sizing::Fit(min, max) => Self {
type_: SizingType::Fit as _,
size: Clay_SizingAxis__bindgen_ty_1 {
minMax: Clay_SizingMinMax { min, max },
},
},
Sizing::Grow(min, max) => Self {
type_: SizingType::Grow as _,
size: Clay_SizingAxis__bindgen_ty_1 {
minMax: Clay_SizingMinMax { min, max },
},
},
Sizing::Fixed(size) => Self {
type_: SizingType::Fixed as _,
size: Clay_SizingAxis__bindgen_ty_1 {
minMax: Clay_SizingMinMax {
min: size,
max: size,
},
},
},
Sizing::Percent(percent) => Self {
type_: SizingType::Percent as _,
size: Clay_SizingAxis__bindgen_ty_1 { percent },
},
}
}
}
#[derive(Debug, Default)]
pub struct Padding {
pub left: u16,
pub right: u16,
pub top: u16,
pub bottom: u16,
}
impl Padding {
pub fn new(left: u16, right: u16, top: u16, bottom: u16) -> Self {
Self {
left,
right,
top,
bottom,
}
}
pub fn all(value: u16) -> Self {
Self::new(value, value, value, value)
}
pub fn horizontal(value: u16) -> Self {
Self::new(value, value, 0, 0)
}
pub fn vertical(value: u16) -> Self {
Self::new(0, 0, value, value)
}
}
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum LayoutAlignmentX {
Left = Clay_LayoutAlignmentX_CLAY_ALIGN_X_LEFT,
Center = Clay_LayoutAlignmentX_CLAY_ALIGN_X_CENTER,
Right = Clay_LayoutAlignmentX_CLAY_ALIGN_X_RIGHT,
}
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum LayoutAlignmentY {
Top = Clay_LayoutAlignmentY_CLAY_ALIGN_Y_TOP,
Center = Clay_LayoutAlignmentY_CLAY_ALIGN_Y_CENTER,
Bottom = Clay_LayoutAlignmentY_CLAY_ALIGN_Y_BOTTOM,
}
#[derive(Debug, Copy, Clone)]
pub struct Alignment {
pub x: LayoutAlignmentX,
pub y: LayoutAlignmentY,
}
impl Alignment {
pub fn new(x: LayoutAlignmentX, y: LayoutAlignmentY) -> Self {
Self { x, y }
}
}
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum LayoutDirection {
LeftToRight = Clay_LayoutDirection_CLAY_LEFT_TO_RIGHT,
TopToBottom = Clay_LayoutDirection_CLAY_TOP_TO_BOTTOM,
}
pub struct LayoutBuilder<
'declaration,
'render,
ImageElementData: 'render,
CustomElementData: 'render,
> {
parent: &'declaration mut Declaration<'render, ImageElementData, CustomElementData>,
}
impl<'declaration, 'render, ImageElementData: 'render, CustomElementData: 'render>
LayoutBuilder<'declaration, 'render, ImageElementData, CustomElementData>
{
#[inline]
pub fn new(
parent: &'declaration mut Declaration<'render, ImageElementData, CustomElementData>,
) -> Self {
LayoutBuilder { parent }
}
#[inline]
pub fn width(&mut self, width: Sizing) -> &mut Self {
self.parent.inner.layout.sizing.width = width.into();
self
}
#[inline]
pub fn height(&mut self, height: Sizing) -> &mut Self {
self.parent.inner.layout.sizing.height = height.into();
self
}
#[inline]
pub fn padding(&mut self, padding: Padding) -> &mut Self {
self.parent.inner.layout.padding.left = padding.left;
self.parent.inner.layout.padding.right = padding.right;
self.parent.inner.layout.padding.top = padding.top;
self.parent.inner.layout.padding.bottom = padding.bottom;
self
}
#[inline]
pub fn child_gap(&mut self, child_gap: u16) -> &mut Self {
self.parent.inner.layout.childGap = child_gap;
self
}
#[inline]
pub fn child_alignment(&mut self, child_alignment: Alignment) -> &mut Self {
self.parent.inner.layout.childAlignment.x = child_alignment.x as _;
self.parent.inner.layout.childAlignment.y = child_alignment.y as _;
self
}
#[inline]
pub fn direction(&mut self, direction: LayoutDirection) -> &mut Self {
self.parent.inner.layout.layoutDirection = direction as _;
self
}
#[inline]
pub fn end(&mut self) -> &mut Declaration<'render, ImageElementData, CustomElementData> {
self.parent
}
}
#[macro_export]
macro_rules! fit {
($min:expr, $max:expr) => {
$crate::layout::Sizing::Fit($min, $max)
};
($min:expr) => {
fit!($min, f32::MAX)
};
() => {
fit!(0.0)
};
}
#[macro_export]
macro_rules! grow {
($min:expr, $max:expr) => {
$crate::layout::Sizing::Grow($min, $max)
};
($min:expr) => {
grow!($min, f32::MAX)
};
() => {
grow!(0.0)
};
}
#[macro_export]
macro_rules! fixed {
($val:expr) => {
$crate::layout::Sizing::Fixed($val)
};
}
#[macro_export]
macro_rules! percent {
($percent:expr) => {{
const _: () = assert!(
$percent >= 0.0 && $percent <= 1.0,
"Percent value must be between 0.0 and 1.0 inclusive!"
);
$crate::layout::Sizing::Percent($percent)
}};
}
#[cfg(test)]
mod test {
use super::*;
use crate::{fit, fixed, grow, percent};
#[test]
fn fit_macro() {
let both_args = fit!(12.0, 34.0);
assert!(matches!(both_args, Sizing::Fit(12.0, 34.0)));
let one_arg = fit!(12.0);
assert!(matches!(one_arg, Sizing::Fit(12.0, f32::MAX)));
let zero_args = fit!();
assert!(matches!(zero_args, Sizing::Fit(0.0, f32::MAX)));
}
#[test]
fn grow_macro() {
let both_args = grow!(12.0, 34.0);
assert!(matches!(both_args, Sizing::Grow(12.0, 34.0)));
let one_arg = grow!(12.0);
assert!(matches!(one_arg, Sizing::Grow(12.0, f32::MAX)));
let zero_args = grow!();
assert!(matches!(zero_args, Sizing::Grow(0.0, f32::MAX)));
}
#[test]
fn fixed_macro() {
let value = fixed!(123.0);
assert!(matches!(value, Sizing::Fixed(123.0)));
}
#[test]
fn percent_macro() {
let value = percent!(0.5);
assert!(matches!(value, Sizing::Percent(0.5)));
}
}