hobo_css/properties/
grid.rs

1use crate::prelude::*;
2
3crate::macros::easy_enum! {row-gap normal [unit]}
4crate::macros::easy_enum! {column-gap normal [unit]}
5crate::macros::easy_enum! {grid-gap normal [unit]}
6
7/*
8css::grid!(
9	column,
10	// [*-gap] | [grid-template-*] >> [grid-auto-*]
11	columns (32 px) | (1 fr) (50 px) repeat(5, (1 fr)) >> 1 fr,
12	rows >> 1 fr,
13)
14*/
15
16#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
17pub enum GridSpan {
18	Auto,
19	Initial,
20	Inherit,
21	Unset,
22	Span(i32),
23	Absolute(i32),
24}
25
26impl std::fmt::Display for GridSpan {
27	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28		match self {
29			Self::Auto => "auto".fmt(f),
30			Self::Initial => "initial".fmt(f),
31			Self::Inherit => "inherit".fmt(f),
32			Self::Unset => "unset".fmt(f),
33			Self::Span(x) => write!(f, "span {}", x),
34			Self::Absolute(x) => x.fmt(f),
35		}
36	}
37}
38
39#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
40pub enum GridAutoFlow {
41	Inherit,
42	Initial,
43	Unset,
44	Row,
45	Column,
46	RowDense,
47	ColumnDense,
48}
49
50#[rustfmt::skip]
51impl std::fmt::Display for GridAutoFlow {
52	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53		match self {
54			Self::Inherit     => "grid-auto-flow:inherit;".fmt(f),
55			Self::Initial     => "grid-auto-flow:initial;".fmt(f),
56			Self::Unset       => "grid-auto-flow:unset;".fmt(f),
57			Self::Row         => "grid-auto-flow:row;".fmt(f),
58			Self::Column      => "grid-auto-flow:column;".fmt(f),
59			Self::RowDense    => "grid-auto-flow:row dense;".fmt(f),
60			Self::ColumnDense => "grid-auto-flow:column dense;".fmt(f),
61		}
62	}
63}
64
65#[macro_export]
66macro_rules! grid_auto_flow {
67	(inherit)      => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::Inherit)};
68	(initial)      => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::Initial)};
69	(unset)        => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::Unset)};
70	(row)          => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::Row)};
71	(column)       => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::Column)};
72	(row dense)    => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::RowDense)};
73	(column dense) => {$crate::Property::GridAutoFlow($crate::GridAutoFlow::ColumnDense)};
74}
75
76// what follows is not a great bunch of structs and macros, but it covers basic grid usage
77// the actual grid syntax is absolutely bananas and nothing short of a full grammar parser would suffice
78
79#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
80pub enum GridRepeatNumber {
81	AutoFit,
82	AutoFill,
83	Some(u32),
84}
85
86#[rustfmt::skip]
87impl std::fmt::Display for GridRepeatNumber {
88	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89		match self {
90			Self::AutoFit  => "auto-fit".fmt(f),
91			Self::AutoFill => "auto-fill".fmt(f),
92			Self::Some(x)  => x.fmt(f),
93		}
94	}
95}
96
97#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
98pub struct GridRepeat {
99	pub number: GridRepeatNumber,
100	pub values: Vec<Unit>,
101}
102
103#[rustfmt::skip]
104impl std::fmt::Display for GridRepeat {
105	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106		write!(f, "repeat({},", self.number)?;
107		for value in &self.values {
108			write!(f, " {}", value)?;
109		}
110		")".fmt(f)
111	}
112}
113
114#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
115pub enum GridTemplate {
116	Inherit,
117	Initial,
118	Unset,
119	None,
120	Some(Vec<GridTemplateValue>),
121}
122
123#[rustfmt::skip]
124impl std::fmt::Display for GridTemplate {
125	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126		match self {
127			Self::Inherit     => "inherit".fmt(f),
128			Self::Initial     => "initial".fmt(f),
129			Self::Unset       => "unset".fmt(f),
130			Self::None        => "none".fmt(f),
131			Self::Some(values)     => {
132				if let Some((first, rest)) = values.split_first() {
133					write!(f, "{}", first)?;
134					for value in rest {
135						write!(f, " {}", value)?;
136					}
137				}
138				Ok(())
139			},
140		}
141	}
142}
143
144#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
145pub enum GridTemplateValue {
146	Repeat(GridRepeat),
147	Unit(Unit),
148}
149
150#[rustfmt::skip]
151impl std::fmt::Display for GridTemplateValue {
152	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153		match self {
154			Self::Unit(x) => x.fmt(f),
155			Self::Repeat(x) => x.fmt(f),
156		}
157	}
158}
159
160#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
161pub enum GridAuto {
162	Inherit,
163	Initial,
164	Unset,
165	Auto,
166	Some(Vec<Unit>),
167}
168
169#[rustfmt::skip]
170impl std::fmt::Display for GridAuto {
171	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172		match self {
173			Self::Inherit => "inherit".fmt(f),
174			Self::Initial => "initial".fmt(f),
175			Self::Unset   => "unset".fmt(f),
176			Self::Auto    => "auto".fmt(f),
177			Self::Some(units) => {
178				if let Some((first, rest)) = units.split_first() {
179					write!(f, "{}", first)?;
180					for unit in rest {
181						write!(f, " {}", unit)?;
182					}
183				}
184				Ok(())
185			},
186		}
187	}
188}
189
190#[doc(hidden)]
191#[macro_export]
192macro_rules! __repeat_number {
193	(auto-fit) => {$crate::GridRepeatNumber::AutoFit};
194	(auto-fill) => {$crate::GridRepeatNumber::AutoFill};
195	($x:expr) => {$crate::GridRepeatNumber::Some($x)};
196}
197
198#[doc(hidden)]
199#[macro_export]
200macro_rules! __nested_unit {
201	(($($tt:tt)+)) => {$crate::unit!($($tt)+)};
202}
203
204#[doc(hidden)]
205#[macro_export]
206macro_rules! __repeat {
207	($($repeat_number:tt)-+, $($v:tt)+) => {
208		$crate::GridRepeat {
209			number: $crate::__repeat_number!($($repeat_number)-+),
210			values: vec![$($crate::__nested_unit!($v)),+],
211		}
212	};
213}
214
215#[doc(hidden)]
216#[macro_export]
217macro_rules! __grid_template_value {
218	(repeat($($tt:tt)+)) => {$crate::GridTemplateValue::Repeat($crate::__repeat!($($tt)+))};
219	(($($tt:tt)+)) => {$crate::GridTemplateValue::Unit($crate::unit!($($tt)+))};
220}
221
222#[doc(hidden)]
223#[macro_export]
224macro_rules! __grid_template {
225	(
226		kind = $kind:ident,
227		acc = $acc:expr,
228		current = ($($current:tt)+),
229		rest = ($(,)*),
230	) => {{
231		$acc.push($crate::__grid_template_value!($($current)+));
232		let acc = $acc;
233		$crate::paste::item!{$crate::Property::[<GridTemplate $kind>]($crate::GridTemplate::Some(acc))}
234	}};
235	(
236		kind = $kind:ident,
237		acc = $acc:expr,
238		current = ($($current:tt)+),
239		rest = (, $($rest:tt)*),
240	) => {{
241		$acc.push($crate::__grid_template_value!($($current)+));
242		$crate::__grid_template!(
243			kind = $kind,
244			acc = $acc,
245			current = (),
246			rest = ($($rest)*),
247		)
248	}};
249	(
250		kind = $kind:ident,
251		acc = $acc:expr,
252		current = ($($current:tt)*),
253		rest = ($token:tt $($rest:tt)*),
254	) => {
255		$crate::__grid_template!(
256			kind = $kind,
257			acc = $acc,
258			current = ($($current)* $token),
259			rest = ($($rest)*),
260		)
261	};
262}
263
264#[macro_export]
265macro_rules! grid_template_columns {
266	($($tt:tt)+) => {{
267		let mut acc = Vec::new();
268		$crate::__grid_template!(
269			kind = Columns,
270			acc = acc,
271			current = (),
272			rest = ($($tt)+),
273		)
274	}};
275}
276
277#[macro_export]
278macro_rules! grid_template_rows {
279	($($tt:tt)+) => {{
280		let mut acc = Vec::new();
281		$crate::__grid_template!(
282			kind = Rows,
283			acc = acc,
284			current = (),
285			rest = ($($tt)+),
286		)
287	}};
288}