1#[macro_export]
22macro_rules! vstack {
23 (gap: $gap:expr; $($child:expr),* $(,)?) => {{
25 $crate::widget::vstack()
26 .gap($gap)
27 $(.child($child))*
28 }};
29 ($($child:expr),* $(,)?) => {{
31 $crate::widget::vstack()
32 $(.child($child))*
33 }};
34}
35
36#[macro_export]
55macro_rules! hstack {
56 (gap: $gap:expr; $($child:expr),* $(,)?) => {{
58 $crate::widget::hstack()
59 .gap($gap)
60 $(.child($child))*
61 }};
62 ($($child:expr),* $(,)?) => {{
64 $crate::widget::hstack()
65 $(.child($child))*
66 }};
67}
68
69#[macro_export]
91macro_rules! bordered {
92 ($border_type:ident, $title:expr; $child:expr) => {{
94 $crate::widget::Border::$border_type()
95 .title($title)
96 .child($child)
97 }};
98 ($title:expr; $child:expr) => {{
100 $crate::widget::Border::single().title($title).child($child)
101 }};
102 ($child:expr) => {{
104 $crate::widget::Border::single().child($child)
105 }};
106}
107
108#[macro_export]
120macro_rules! text {
121 ($content:expr, $color:ident, bold) => {{
123 $crate::widget::Text::new($content)
124 .fg($crate::style::Color::$color)
125 .bold()
126 }};
127 ($content:expr, $color:ident, italic) => {{
128 $crate::widget::Text::new($content)
129 .fg($crate::style::Color::$color)
130 .italic()
131 }};
132 ($content:expr, red) => {{
134 $crate::widget::Text::error($content)
135 }};
136 ($content:expr, green) => {{
137 $crate::widget::Text::success($content)
138 }};
139 ($content:expr, yellow) => {{
140 $crate::widget::Text::warning($content)
141 }};
142 ($content:expr, cyan) => {{
143 $crate::widget::Text::info($content)
144 }};
145 ($content:expr, $color:ident) => {{
146 $crate::widget::Text::new($content).fg($crate::style::Color::$color)
147 }};
148 ($content:expr) => {{
150 $crate::widget::Text::new($content)
151 }};
152}
153
154#[macro_export]
173macro_rules! ui {
174 (vstack(gap: $gap:expr) { $($child:tt)* }) => {{
176 $crate::widget::vstack()
177 .gap($gap)
178 $(.child($crate::ui!(@child $child)))*
179 }};
180 (vstack { $($child:tt)* }) => {{
182 $crate::widget::vstack()
183 $(.child($crate::ui!(@child $child)))*
184 }};
185 (hstack(gap: $gap:expr) { $($child:tt)* }) => {{
187 $crate::widget::hstack()
188 .gap($gap)
189 $(.child($crate::ui!(@child $child)))*
190 }};
191 (hstack { $($child:tt)* }) => {{
193 $crate::widget::hstack()
194 $(.child($crate::ui!(@child $child)))*
195 }};
196 (@child vstack $($rest:tt)*) => {{
198 $crate::ui!(vstack $($rest)*)
199 }};
200 (@child hstack $($rest:tt)*) => {{
201 $crate::ui!(hstack $($rest)*)
202 }};
203 (@child $expr:expr) => {{
205 $expr
206 }};
207}
208
209#[cfg(test)]
210mod tests {
211 use crate::layout::Rect;
212 use crate::render::Buffer;
213 use crate::widget::{RenderContext, Text, View};
214
215 #[test]
216 fn test_vstack_macro() {
217 let stack = vstack![Text::new("Line 1"), Text::new("Line 2"),];
218 assert_eq!(stack.len(), 2);
219 }
220
221 #[test]
222 fn test_vstack_macro_with_gap() {
223 let stack = vstack![gap: 2;
224 Text::new("A"),
225 Text::new("B"),
226 ];
227 assert_eq!(stack.len(), 2);
228 }
229
230 #[test]
231 fn test_hstack_macro() {
232 let stack = hstack![Text::new("Left"), Text::new("Right"),];
233 assert_eq!(stack.len(), 2);
234 }
235
236 #[test]
237 fn test_text_macro() {
238 let t = text!("Hello");
239 assert_eq!(t.content(), "Hello");
240
241 let t = text!("Error", red);
242 assert_eq!(t.content(), "Error");
243 }
244
245 #[test]
246 fn test_bordered_macro() {
247 let b = bordered![Text::new("Content")];
248 let mut buffer = Buffer::new(10, 5);
250 let area = Rect::new(0, 0, 10, 5);
251 let mut ctx = RenderContext::new(&mut buffer, area);
252 b.render(&mut ctx);
253 }
254
255 #[test]
256 fn test_bordered_macro_with_title() {
257 let b = bordered!["Title"; Text::new("Content")];
258 let mut buffer = Buffer::new(20, 5);
259 let area = Rect::new(0, 0, 20, 5);
260 let mut ctx = RenderContext::new(&mut buffer, area);
261 b.render(&mut ctx);
262 }
263
264 #[test]
265 fn test_nested_layout() {
266 let layout = vstack![
267 Text::heading("Title"),
268 hstack![Text::new("Left"), Text::new("Right"),],
269 Text::muted("Footer"),
270 ];
271 assert_eq!(layout.len(), 3);
272 }
273}