bevy_aoui_widgets/dsl/
layouts.rs

1
2use bevy::math::{Vec2, UVec2};
3use bevy_aoui::{Size2, FlexDir, Container, Layout, Alignment};
4pub use bevy_aoui::bundles::LinebreakBundle as Linebreak;
5
6/// Construct a dummy entity for linebreak in a layout.
7#[macro_export]
8macro_rules! linebreak {
9    (($commands: expr $(, $tt:expr)*) $(,)?) => {
10        $commands.spawn(::bevy_aoui::bundles::LinebreakBundle::default()).id()
11    };
12    (($commands: expr $(, $tt:expr)*) {}) => {
13        $commands.spawn(::bevy_aoui::bundles::LinebreakBundle::default()).id()
14    };
15    (($commands: expr $(, $tt:expr)*), $size: expr $(,)?) => {
16        {
17            use $crate::dsl::DslInto;
18            let OneOrTwo(size) = $size.dinto();
19            $commands.spawn(::bevy_aoui::bundles::LinebreakBundle::new(size)).id()
20        }
21    };
22    (($commands: expr $(, $tt:expr)*) {$size: expr}) => {
23        {
24            use $crate::dsl::DslInto;
25            let size: ::bevy_aoui::Size2;
26            OneOrTwo(size) = $size.dinto();
27            $commands.spawn(::bevy_aoui::bundles::LinebreakBundle::new(size)).id()
28        }
29    };
30}
31
32use crate::widget_extension;
33
34use super::util::OneOrTwo;
35
36
37widget_extension! {
38    pub struct DynamicFrameBuilder {
39        margin: OneOrTwo<Size2>,
40        pub x: Option<bool>,
41        pub y: Option<bool>,
42    },
43    this, commands,
44    components: (
45        Container {
46            layout: Layout::Dynamic { 
47                x: this.x.unwrap_or(true), 
48                y: this.y.unwrap_or(true), 
49            },
50            margin: this.margin.0,
51        }
52    ),
53}
54
55#[derive(Debug, Clone, Copy)]
56pub enum SpanContainerNames {
57    Compact,
58    Span,
59    Paragraph,
60}
61
62#[derive(Debug, Clone, Copy)]
63pub enum GridContainerNames {
64    FixedGrid,
65    SizedGrid,
66    FlexTable,
67    FixedTable,
68    SizedTable,
69}
70
71widget_extension! {
72    pub struct SpanContainerBuilder {
73        pub r#type: Option<SpanContainerNames>,
74        pub direction: Option<FlexDir>,
75        pub stack: Option<FlexDir>,
76        pub stretch: bool,
77        pub margin: OneOrTwo<Size2>,
78    },
79    this, commands,
80    components: (
81        Container {
82            layout: match this.r#type {
83                Some(SpanContainerNames::Compact) => Layout::Compact { 
84                    direction: this.direction.unwrap_or(FlexDir::LeftToRight) 
85                },
86                Some(SpanContainerNames::Span) => Layout::Span { 
87                    direction: this.direction.unwrap_or(FlexDir::LeftToRight), 
88                    stretch: this.stretch,
89                },
90                Some(SpanContainerNames::Paragraph) => Layout::Paragraph { 
91                    direction: this.direction.unwrap_or(FlexDir::LeftToRight), 
92                    stack: this.stack.unwrap_or(match this.direction {
93                        Some(FlexDir::BottomToTop|FlexDir::TopToBottom) => FlexDir::LeftToRight,
94                        _ => FlexDir::TopToBottom,
95                    }), 
96                    stretch: this.stretch
97                },
98                None => panic!("Please specify the container type."),
99            },
100            margin: this.margin.0
101        }
102    ),
103}
104
105widget_extension! {
106    pub struct GridContainerBuilder {
107        pub r#type: Option<GridContainerNames>,
108        pub cell_count: Option<UVec2>,
109        pub cell_size: Option<Vec2>,
110        pub column_count: Option<usize>,
111        pub columns: Vec<f32>,
112        pub row: Option<FlexDir>,
113        pub column: Option<FlexDir>,
114        pub alignment: Option<Alignment>,
115        pub stretch: bool,
116        pub margin: OneOrTwo<Size2>,
117    },
118    this, commands,
119    components: (
120        {
121            let row_dir = this.row.unwrap_or(FlexDir::LeftToRight);
122            let column_dir = this.column.unwrap_or(match row_dir {
123                FlexDir::LeftToRight | FlexDir::RightToLeft => FlexDir::TopToBottom,
124                FlexDir::BottomToTop | FlexDir::TopToBottom => FlexDir::LeftToRight,
125            });
126            let alignment = this.alignment.unwrap_or(match row_dir {
127                FlexDir::LeftToRight | FlexDir::RightToLeft => Alignment::Left,
128                FlexDir::BottomToTop | FlexDir::TopToBottom => Alignment::Top,
129            });
130            Container {
131                layout: match this.r#type {
132                    Some(GridContainerNames::FixedGrid) => Layout::Grid {
133                        cell: bevy_aoui::Cells::Counted(this.cell_count.expect("cell_count must be specified.")),
134                        row_dir,
135                        column_dir,
136                        alignment,
137                        stretch: this.stretch,
138                    },
139                    Some(GridContainerNames::SizedGrid) => Layout::Grid {
140                        cell: bevy_aoui::Cells::Sized(this.cell_size.expect("cell_size must be specified.")),
141                        row_dir,
142                        column_dir,
143                        alignment,
144                        stretch: this.stretch,
145                    },
146                    Some(GridContainerNames::FlexTable) => Layout::Table {
147                        columns: bevy_aoui::Columns::Dynamic(this.column_count.unwrap_or(usize::MAX)),
148                        row_dir,
149                        column_dir,
150                        stretch: this.stretch,
151                    },
152                    Some(GridContainerNames::FixedTable) => Layout::Table {
153                        columns: bevy_aoui::Columns::Porportions(this.columns),
154                        row_dir,
155                        column_dir,
156                        stretch: this.stretch,
157                    },
158                    Some(GridContainerNames::SizedTable) => Layout::Table {
159                        columns: bevy_aoui::Columns::Sized(this.columns),
160                        row_dir,
161                        column_dir,
162                        stretch: this.stretch,
163                    },
164                    None => panic!("Please specify the container type."),
165                },
166                margin: this.margin.0,
167            }
168        }
169    ),
170}
171
172/// Construct a compact layout.
173#[macro_export]
174macro_rules! compact {
175    {$commands: tt {$($tt:tt)*}} => {
176        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
177            r#type: $crate::dsl::SpanContainerNames::Compact,
178            $($tt)*
179        })
180    };
181}
182
183/// Construct a horizotal left to right compact layout.
184#[macro_export]
185macro_rules! hbox {
186    {$commands: tt {$($tt:tt)*}} => {
187        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
188            r#type: $crate::dsl::SpanContainerNames::Compact,
189            direction: ::bevy_aoui::FlexDir::LeftToRight,
190            $($tt)*
191        })
192    };
193}
194
195/// Construct a vertical top to bottom compact layout.
196#[macro_export]
197macro_rules! vbox {
198    {$commands: tt {$($tt:tt)*}} => {
199        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
200            r#type: $crate::dsl::SpanContainerNames::Compact,
201            direction: ::bevy_aoui::FlexDir::TopToBottom,
202            $($tt)*
203        })
204    };
205}
206
207/// Construct a span layout.
208#[macro_export]
209macro_rules! span {
210    {$commands: tt {$($tt:tt)*}} => {
211        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
212            r#type: $crate::dsl::SpanContainerNames::Span,
213            $($tt)*
214        })
215    };
216}
217
218/// Construct a horizontal left to right span layout.
219#[macro_export]
220macro_rules! hspan {
221    {$commands: tt {$($tt:tt)*}} => {
222        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
223            r#type: $crate::dsl::SpanContainerNames::Span,
224            direction: ::bevy_aoui::FlexDir::LeftToRight,
225            $($tt)*
226        })
227    };
228}
229
230/// Construct a vertical top to bottom span layout.
231#[macro_export]
232macro_rules! vspan {
233    {$commands: tt {$($tt:tt)*}} => {
234        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
235            r#type: $crate::dsl::SpanContainerNames::Span,
236            direction: ::bevy_aoui::FlexDir::TopToBottom,
237            $($tt)*
238        })
239    };
240}
241
242/// Construct a paragtaph layout.
243#[macro_export]
244macro_rules! paragraph {
245    {$commands: tt {$($tt:tt)*}} => {
246        $crate::meta_dsl!($commands [$crate::dsl::builders::SpanContainerBuilder] {
247            r#type: $crate::dsl::SpanContainerNames::Paragraph,
248            $($tt)*
249        })
250    };
251}
252
253/// Construct a fixed grid layout.
254#[macro_export]
255macro_rules! fixed_grid {
256    {$commands: tt {$($tt:tt)*}} => {
257        $crate::meta_dsl!($commands [$crate::dsl::builders::GridContainerBuilder] {
258            r#type: $crate::dsl::GridContainerNames::FixedGrid,
259            $($tt)*
260        })
261    };
262}
263
264/// Construct a sized grid layout.
265#[macro_export]
266macro_rules! sized_grid {
267    {$commands: tt {$($tt:tt)*}} => {
268        $crate::meta_dsl!($commands [$crate::dsl::builders::GridContainerBuilder] {
269            r#type: $crate::dsl::GridContainerNames::SizedGrid,
270            $($tt)*
271        })
272    };
273}
274
275/// Construct a flex table layout.
276#[macro_export]
277macro_rules! flex_table {
278    {$commands: tt {$($tt:tt)*}} => {
279        $crate::meta_dsl!($commands [$crate::dsl::builders::GridContainerBuilder] {
280            r#type: $crate::dsl::GridContainerNames::FlexTable,
281            $($tt)*
282        })
283    };
284}
285
286/// Construct a fixed table layout.
287#[macro_export]
288macro_rules! fixed_table {
289    {$commands: tt {$($tt:tt)*}} => {
290        $crate::meta_dsl!($commands [$crate::dsl::builders::GridContainerBuilder] {
291            r#type: $crate::dsl::GridContainerNames::FixedTable,
292            $($tt)*
293        })
294    };
295}
296
297/// Construct a sized table layout.
298#[macro_export]
299macro_rules! sized_table {
300    {$commands: tt {$($tt:tt)*}} => {
301        $crate::meta_dsl!($commands [$crate::dsl::builders::GridContainerBuilder] {
302            r#type: $crate::dsl::GridContainerNames::SizedTable,
303            $($tt)*
304        })
305    };
306}