1#[macro_export]
23macro_rules! layout {
24 ($title:expr, $subtitle:expr, $knob_size:expr, { $($body:tt)* }) => {{
25 let rows = $crate::__layout_rows!( [] $($body)* );
26 $crate::layout::PluginLayout::build(
27 $crate::layout::HeaderTitles::pair($title, $subtitle),
28 rows,
29 $knob_size,
30 )
31 }};
32}
33
34#[macro_export]
35#[doc(hidden)]
36macro_rules! __layout_rows {
37 ( [ $($rows:expr),* ] ) => {
38 vec![ $($rows),* ]
39 };
40
41 ( [ $($rows:expr),* ] row { $($widgets:tt)* } $($rest:tt)* ) => {
42 $crate::__layout_rows!(
43 [ $($rows,)* $crate::layout::KnobRow {
44 label: None,
45 knobs: $crate::__layout_widgets!( [] $($widgets)* ),
46 } ]
47 $($rest)*
48 )
49 };
50
51 ( [ $($rows:expr),* ] section($label:expr) { $($widgets:tt)* } $($rest:tt)* ) => {
52 $crate::__layout_rows!(
53 [ $($rows,)* $crate::layout::KnobRow {
54 label: Some($label),
55 knobs: $crate::__layout_widgets!( [] $($widgets)* ),
56 } ]
57 $($rest)*
58 )
59 };
60}
61
62#[macro_export]
63#[doc(hidden)]
64macro_rules! __layout_widgets {
65 ( [ $($w:expr),* ] ) => {
67 vec![ $($w),* ]
68 };
69
70 ( [ $($w:expr),* ] knob($id:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
73 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::knob($id, $label).with_span($n) ] $($rest)* )
74 };
75 ( [ $($w:expr),* ] slider($id:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
76 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::slider($id, $label).with_span($n) ] $($rest)* )
77 };
78 ( [ $($w:expr),* ] toggle($id:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
79 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::toggle($id, $label).with_span($n) ] $($rest)* )
80 };
81 ( [ $($w:expr),* ] meter($ids:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
82 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::meter($ids, $label).with_span($n) ] $($rest)* )
83 };
84 ( [ $($w:expr),* ] xy_pad($x:expr, $y:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
85 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::xy_pad($x, $y, $label).with_span($n) ] $($rest)* )
86 };
87
88 ( [ $($w:expr),* ] knob($id:expr, $label:expr) $($rest:tt)* ) => {
91 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::knob($id, $label) ] $($rest)* )
92 };
93 ( [ $($w:expr),* ] slider($id:expr, $label:expr) $($rest:tt)* ) => {
94 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::slider($id, $label) ] $($rest)* )
95 };
96 ( [ $($w:expr),* ] toggle($id:expr, $label:expr) $($rest:tt)* ) => {
97 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::toggle($id, $label) ] $($rest)* )
98 };
99 ( [ $($w:expr),* ] meter($ids:expr, $label:expr) $($rest:tt)* ) => {
100 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::meter($ids, $label) ] $($rest)* )
101 };
102 ( [ $($w:expr),* ] xy_pad($x:expr, $y:expr, $label:expr) $($rest:tt)* ) => {
103 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::xy_pad($x, $y, $label) ] $($rest)* )
104 };
105}
106
107#[macro_export]
153macro_rules! grid {
154 ({ $($body:tt)* }) => {{
156 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
157 }};
158 (cols: $cols:expr, { $($body:tt)* }) => {{
160 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
161 .with_cols($cols)
162 }};
163 (cell: $cell:expr, { $($body:tt)* }) => {{
165 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
166 .with_cell_size($cell)
167 }};
168 (cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
170 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
171 .with_grid($cols, $cell)
172 }};
173
174 (title: $title:expr, subtitle: $subtitle:expr, { $($body:tt)* }) => {{
178 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
179 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
180 }};
181 (title: $title:expr, subtitle: $subtitle:expr, cols: $cols:expr, { $($body:tt)* }) => {{
183 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
184 .with_cols($cols)
185 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
186 }};
187 (title: $title:expr, subtitle: $subtitle:expr, cell: $cell:expr, { $($body:tt)* }) => {{
189 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
190 .with_cell_size($cell)
191 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
192 }};
193 (title: $title:expr, subtitle: $subtitle:expr, cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
195 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
196 .with_grid($cols, $cell)
197 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
198 }};
199
200 (title: $title:expr, { $($body:tt)* }) => {{
202 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
203 .with_title($title)
204 }};
205 (title: $title:expr, cols: $cols:expr, { $($body:tt)* }) => {{
206 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
207 .with_cols($cols)
208 .with_title($title)
209 }};
210 (title: $title:expr, cell: $cell:expr, { $($body:tt)* }) => {{
211 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
212 .with_cell_size($cell)
213 .with_title($title)
214 }};
215 (title: $title:expr, cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
216 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
217 .with_grid($cols, $cell)
218 .with_title($title)
219 }};
220
221 (subtitle: $subtitle:expr, { $($body:tt)* }) => {{
223 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
224 .with_subtitle($subtitle)
225 }};
226 (subtitle: $subtitle:expr, cols: $cols:expr, { $($body:tt)* }) => {{
227 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
228 .with_cols($cols)
229 .with_subtitle($subtitle)
230 }};
231 (subtitle: $subtitle:expr, cell: $cell:expr, { $($body:tt)* }) => {{
232 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
233 .with_cell_size($cell)
234 .with_subtitle($subtitle)
235 }};
236 (subtitle: $subtitle:expr, cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
237 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
238 .with_grid($cols, $cell)
239 .with_subtitle($subtitle)
240 }};
241}
242
243#[macro_export]
244#[doc(hidden)]
245macro_rules! __grid_sections {
246 ($($body:tt)*) => {{
247 let mut _widgets: Vec<$crate::layout::GridWidget> = Vec::new();
248 let mut _breaks: Vec<(usize, &'static str)> = Vec::new();
249 $crate::__grid_items!(_widgets, _breaks, $($body)*);
250 let mut _sections: Vec<$crate::layout::Section> = Vec::new();
252 let mut _cur_widgets: Vec<$crate::layout::GridWidget> = Vec::new();
253 let mut _cur_label: Option<&'static str> = None;
254 for (i, w) in _widgets.into_iter().enumerate() {
255 if let Some(&(_, label)) = _breaks.iter().find(|(idx, _)| *idx == i) {
256 if !_cur_widgets.is_empty() || _cur_label.is_some() {
257 _sections.push($crate::layout::Section {
258 label: _cur_label,
259 widgets: std::mem::take(&mut _cur_widgets),
260 });
261 }
262 _cur_label = Some(label);
263 }
264 _cur_widgets.push(w);
265 }
266 if !_cur_widgets.is_empty() || _cur_label.is_some() {
267 _sections.push($crate::layout::Section {
268 label: _cur_label,
269 widgets: _cur_widgets,
270 });
271 }
272 _sections
273 }};
274}
275
276#[macro_export]
277#[doc(hidden)]
278macro_rules! __grid_items {
279 ($w:ident, $b:ident) => {};
281 ($w:ident, $b:ident,) => {};
282
283 ($w:ident, $b:ident, section($label:expr) $($rest:tt)*) => {
285 $b.push(($w.len(), $label));
286 $crate::__grid_items!($w, $b, $($rest)*);
287 };
288
289 ($w:ident, $b:ident, knob($id:expr, $label:expr) $($rest:tt)*) => {
291 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::knob($id, $label), $($rest)*);
292 };
293 ($w:ident, $b:ident, slider($id:expr, $label:expr) $($rest:tt)*) => {
294 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::slider($id, $label), $($rest)*);
295 };
296 ($w:ident, $b:ident, toggle($id:expr, $label:expr) $($rest:tt)*) => {
297 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::toggle($id, $label), $($rest)*);
298 };
299 ($w:ident, $b:ident, meter($ids:expr, $label:expr) $($rest:tt)*) => {
300 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::meter($ids, $label), $($rest)*);
301 };
302 ($w:ident, $b:ident, xy_pad($x:expr, $y:expr, $label:expr) $($rest:tt)*) => {
303 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::xy_pad($x, $y, $label), $($rest)*);
304 };
305}
306
307#[macro_export]
308#[doc(hidden)]
309macro_rules! __grid_mods {
310 ($w:ident, $b:ident, $widget:expr, .cols($c:expr) .rows($r:expr) $($rest:tt)*) => {
312 $w.push($widget.cols($c).rows($r));
313 $crate::__grid_items!($w, $b, $($rest)*);
314 };
315 ($w:ident, $b:ident, $widget:expr, .rows($r:expr) .cols($c:expr) $($rest:tt)*) => {
317 $w.push($widget.cols($c).rows($r));
318 $crate::__grid_items!($w, $b, $($rest)*);
319 };
320 ($w:ident, $b:ident, $widget:expr, .cols($c:expr) $($rest:tt)*) => {
322 $w.push($widget.cols($c));
323 $crate::__grid_items!($w, $b, $($rest)*);
324 };
325 ($w:ident, $b:ident, $widget:expr, .rows($r:expr) $($rest:tt)*) => {
327 $w.push($widget.rows($r));
328 $crate::__grid_items!($w, $b, $($rest)*);
329 };
330 ($w:ident, $b:ident, $widget:expr, $($rest:tt)*) => {
332 $w.push($widget);
333 $crate::__grid_items!($w, $b, $($rest)*);
334 };
335}