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),* ] selector($id:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
82 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::selector($id, $label).with_span($n) ] $($rest)* )
83 };
84 ( [ $($w:expr),* ] meter($ids:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
85 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::meter($ids, $label).with_span($n) ] $($rest)* )
86 };
87 ( [ $($w:expr),* ] xy_pad($x:expr, $y:expr, $label:expr) .span($n:expr) $($rest:tt)* ) => {
88 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::xy_pad($x, $y, $label).with_span($n) ] $($rest)* )
89 };
90
91 ( [ $($w:expr),* ] knob($id:expr, $label:expr) $($rest:tt)* ) => {
94 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::knob($id, $label) ] $($rest)* )
95 };
96 ( [ $($w:expr),* ] slider($id:expr, $label:expr) $($rest:tt)* ) => {
97 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::slider($id, $label) ] $($rest)* )
98 };
99 ( [ $($w:expr),* ] toggle($id:expr, $label:expr) $($rest:tt)* ) => {
100 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::toggle($id, $label) ] $($rest)* )
101 };
102 ( [ $($w:expr),* ] selector($id:expr, $label:expr) $($rest:tt)* ) => {
103 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::selector($id, $label) ] $($rest)* )
104 };
105 ( [ $($w:expr),* ] meter($ids:expr, $label:expr) $($rest:tt)* ) => {
106 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::meter($ids, $label) ] $($rest)* )
107 };
108 ( [ $($w:expr),* ] xy_pad($x:expr, $y:expr, $label:expr) $($rest:tt)* ) => {
109 $crate::__layout_widgets!( [ $($w,)* $crate::layout::KnobDef::xy_pad($x, $y, $label) ] $($rest)* )
110 };
111}
112
113#[macro_export]
159macro_rules! grid {
160 ({ $($body:tt)* }) => {{
162 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
163 }};
164 (cols: $cols:expr, { $($body:tt)* }) => {{
166 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
167 .with_cols($cols)
168 }};
169 (cell: $cell:expr, { $($body:tt)* }) => {{
171 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
172 .with_cell_size($cell)
173 }};
174 (cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
176 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
177 .with_grid($cols, $cell)
178 }};
179
180 (title: $title:expr, subtitle: $subtitle:expr, { $($body:tt)* }) => {{
184 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
185 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
186 }};
187 (title: $title:expr, subtitle: $subtitle:expr, cols: $cols:expr, { $($body:tt)* }) => {{
189 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
190 .with_cols($cols)
191 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
192 }};
193 (title: $title:expr, subtitle: $subtitle:expr, cell: $cell:expr, { $($body:tt)* }) => {{
195 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
196 .with_cell_size($cell)
197 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
198 }};
199 (title: $title:expr, subtitle: $subtitle:expr, cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
201 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
202 .with_grid($cols, $cell)
203 .with_titles($crate::layout::HeaderTitles::pair($title, $subtitle))
204 }};
205
206 (title: $title:expr, { $($body:tt)* }) => {{
208 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
209 .with_title($title)
210 }};
211 (title: $title:expr, cols: $cols:expr, { $($body:tt)* }) => {{
212 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
213 .with_cols($cols)
214 .with_title($title)
215 }};
216 (title: $title:expr, cell: $cell:expr, { $($body:tt)* }) => {{
217 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
218 .with_cell_size($cell)
219 .with_title($title)
220 }};
221 (title: $title:expr, cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
222 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
223 .with_grid($cols, $cell)
224 .with_title($title)
225 }};
226
227 (subtitle: $subtitle:expr, { $($body:tt)* }) => {{
229 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
230 .with_subtitle($subtitle)
231 }};
232 (subtitle: $subtitle:expr, cols: $cols:expr, { $($body:tt)* }) => {{
233 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
234 .with_cols($cols)
235 .with_subtitle($subtitle)
236 }};
237 (subtitle: $subtitle:expr, cell: $cell:expr, { $($body:tt)* }) => {{
238 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
239 .with_cell_size($cell)
240 .with_subtitle($subtitle)
241 }};
242 (subtitle: $subtitle:expr, cols: $cols:expr, cell: $cell:expr, { $($body:tt)* }) => {{
243 $crate::layout::GridLayout::build($crate::__grid_sections!($($body)*))
244 .with_grid($cols, $cell)
245 .with_subtitle($subtitle)
246 }};
247}
248
249#[macro_export]
250#[doc(hidden)]
251macro_rules! __grid_sections {
252 ($($body:tt)*) => {{
253 let mut _widgets: Vec<$crate::layout::GridWidget> = Vec::new();
254 let mut _breaks: Vec<(usize, &'static str)> = Vec::new();
255 $crate::__grid_items!(_widgets, _breaks, $($body)*);
256 let mut _sections: Vec<$crate::layout::Section> = Vec::new();
258 let mut _cur_widgets: Vec<$crate::layout::GridWidget> = Vec::new();
259 let mut _cur_label: Option<&'static str> = None;
260 for (i, w) in _widgets.into_iter().enumerate() {
261 if let Some(&(_, label)) = _breaks.iter().find(|(idx, _)| *idx == i) {
262 if !_cur_widgets.is_empty() || _cur_label.is_some() {
263 _sections.push($crate::layout::Section {
264 label: _cur_label,
265 widgets: std::mem::take(&mut _cur_widgets),
266 });
267 }
268 _cur_label = Some(label);
269 }
270 _cur_widgets.push(w);
271 }
272 if !_cur_widgets.is_empty() || _cur_label.is_some() {
273 _sections.push($crate::layout::Section {
274 label: _cur_label,
275 widgets: _cur_widgets,
276 });
277 }
278 _sections
279 }};
280}
281
282#[macro_export]
283#[doc(hidden)]
284macro_rules! __grid_items {
285 ($w:ident, $b:ident) => {};
287 ($w:ident, $b:ident,) => {};
288
289 ($w:ident, $b:ident, section($label:expr) $($rest:tt)*) => {
291 $b.push(($w.len(), $label));
292 $crate::__grid_items!($w, $b, $($rest)*);
293 };
294
295 ($w:ident, $b:ident, knob($id:expr, $label:expr) $($rest:tt)*) => {
297 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::knob($id, $label), $($rest)*);
298 };
299 ($w:ident, $b:ident, slider($id:expr, $label:expr) $($rest:tt)*) => {
300 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::slider($id, $label), $($rest)*);
301 };
302 ($w:ident, $b:ident, toggle($id:expr, $label:expr) $($rest:tt)*) => {
303 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::toggle($id, $label), $($rest)*);
304 };
305 ($w:ident, $b:ident, selector($id:expr, $label:expr) $($rest:tt)*) => {
306 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::selector($id, $label), $($rest)*);
307 };
308 ($w:ident, $b:ident, meter($ids:expr, $label:expr) $($rest:tt)*) => {
309 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::meter($ids, $label), $($rest)*);
310 };
311 ($w:ident, $b:ident, xy_pad($x:expr, $y:expr, $label:expr) $($rest:tt)*) => {
312 $crate::__grid_mods!($w, $b, $crate::layout::GridWidget::xy_pad($x, $y, $label), $($rest)*);
313 };
314}
315
316#[macro_export]
317#[doc(hidden)]
318macro_rules! __grid_mods {
319 ($w:ident, $b:ident, $widget:expr, .cols($c:expr) .rows($r:expr) $($rest:tt)*) => {
321 $w.push($widget.cols($c).rows($r));
322 $crate::__grid_items!($w, $b, $($rest)*);
323 };
324 ($w:ident, $b:ident, $widget:expr, .rows($r:expr) .cols($c:expr) $($rest:tt)*) => {
326 $w.push($widget.cols($c).rows($r));
327 $crate::__grid_items!($w, $b, $($rest)*);
328 };
329 ($w:ident, $b:ident, $widget:expr, .cols($c:expr) $($rest:tt)*) => {
331 $w.push($widget.cols($c));
332 $crate::__grid_items!($w, $b, $($rest)*);
333 };
334 ($w:ident, $b:ident, $widget:expr, .rows($r:expr) $($rest:tt)*) => {
336 $w.push($widget.rows($r));
337 $crate::__grid_items!($w, $b, $($rest)*);
338 };
339 ($w:ident, $b:ident, $widget:expr, $($rest:tt)*) => {
341 $w.push($widget);
342 $crate::__grid_items!($w, $b, $($rest)*);
343 };
344}