borders/
borders.rs

1//! Example demonstrating bordered UI nodes
2
3use bevy::{color::palettes::css::*, ecs::spawn::SpawnIter, prelude::*};
4
5fn main() {
6    App::new()
7        .add_plugins(DefaultPlugins)
8        .add_systems(Startup, setup)
9        .run();
10}
11
12fn setup(mut commands: Commands) {
13    commands.spawn(Camera2d);
14
15    // labels for the different border edges
16    let border_labels = [
17        "None",
18        "All",
19        "Left",
20        "Right",
21        "Top",
22        "Bottom",
23        "Horizontal",
24        "Vertical",
25        "Top Left",
26        "Bottom Left",
27        "Top Right",
28        "Bottom Right",
29        "Top Bottom Right",
30        "Top Bottom Left",
31        "Top Left Right",
32        "Bottom Left Right",
33    ];
34
35    // all the different combinations of border edges
36    // these correspond to the labels above
37    let borders = [
38        UiRect::default(),
39        UiRect::all(px(10)),
40        UiRect::left(px(10)),
41        UiRect::right(px(10)),
42        UiRect::top(px(10)),
43        UiRect::bottom(px(10)),
44        UiRect::horizontal(px(10)),
45        UiRect::vertical(px(10)),
46        UiRect {
47            left: px(20),
48            top: px(10),
49            ..default()
50        },
51        UiRect {
52            left: px(10),
53            bottom: px(20),
54            ..default()
55        },
56        UiRect {
57            right: px(20),
58            top: px(10),
59            ..default()
60        },
61        UiRect {
62            right: px(10),
63            bottom: px(10),
64            ..default()
65        },
66        UiRect {
67            right: px(10),
68            top: px(20),
69            bottom: px(10),
70            ..default()
71        },
72        UiRect {
73            left: px(10),
74            top: px(10),
75            bottom: px(10),
76            ..default()
77        },
78        UiRect {
79            left: px(20),
80            right: px(10),
81            top: px(10),
82            ..default()
83        },
84        UiRect {
85            left: px(10),
86            right: px(10),
87            bottom: px(20),
88            ..default()
89        },
90    ];
91
92    let borders_examples = (
93        Node {
94            margin: UiRect::all(px(25)),
95            align_self: AlignSelf::Stretch,
96            justify_self: JustifySelf::Stretch,
97            flex_wrap: FlexWrap::Wrap,
98            justify_content: JustifyContent::FlexStart,
99            align_items: AlignItems::FlexStart,
100            align_content: AlignContent::FlexStart,
101            ..default()
102        },
103        Children::spawn(SpawnIter(border_labels.into_iter().zip(borders).map(
104            |(label, border)| {
105                (
106                    Node {
107                        flex_direction: FlexDirection::Column,
108                        align_items: AlignItems::Center,
109                        ..default()
110                    },
111                    children![
112                        (
113                            Node {
114                                width: px(50),
115                                height: px(50),
116                                border,
117                                margin: UiRect::all(px(20)),
118                                align_items: AlignItems::Center,
119                                justify_content: JustifyContent::Center,
120                                ..default()
121                            },
122                            BackgroundColor(MAROON.into()),
123                            BorderColor {
124                                top: RED.into(),
125                                bottom: YELLOW.into(),
126                                left: GREEN.into(),
127                                right: BLUE.into(),
128                            },
129                            Outline {
130                                width: px(6),
131                                offset: px(6),
132                                color: Color::WHITE,
133                            },
134                            children![(
135                                Node {
136                                    width: px(10),
137                                    height: px(10),
138                                    ..default()
139                                },
140                                BackgroundColor(YELLOW.into()),
141                            )]
142                        ),
143                        (Text::new(label), TextFont::from_font_size(9.0))
144                    ],
145                )
146            },
147        ))),
148    );
149
150    let non_zero = |x, y| x != px(0) && y != px(0);
151    let border_size = move |x, y| {
152        if non_zero(x, y) {
153            f32::MAX
154        } else {
155            0.
156        }
157    };
158
159    let borders_examples_rounded = (
160        Node {
161            margin: UiRect::all(px(25)),
162            align_self: AlignSelf::Stretch,
163            justify_self: JustifySelf::Stretch,
164            flex_wrap: FlexWrap::Wrap,
165            justify_content: JustifyContent::FlexStart,
166            align_items: AlignItems::FlexStart,
167            align_content: AlignContent::FlexStart,
168            ..default()
169        },
170        Children::spawn(SpawnIter(border_labels.into_iter().zip(borders).map(
171            move |(label, border)| {
172                (
173                    Node {
174                        flex_direction: FlexDirection::Column,
175                        align_items: AlignItems::Center,
176                        ..default()
177                    },
178                    children![
179                        (
180                            Node {
181                                width: px(50),
182                                height: px(50),
183                                border,
184                                margin: UiRect::all(px(20)),
185                                align_items: AlignItems::Center,
186                                justify_content: JustifyContent::Center,
187                                ..default()
188                            },
189                            BackgroundColor(MAROON.into()),
190                            BorderColor {
191                                top: RED.into(),
192                                bottom: YELLOW.into(),
193                                left: GREEN.into(),
194                                right: BLUE.into(),
195                            },
196                            BorderRadius::px(
197                                border_size(border.left, border.top),
198                                border_size(border.right, border.top),
199                                border_size(border.right, border.bottom,),
200                                border_size(border.left, border.bottom),
201                            ),
202                            Outline {
203                                width: px(6),
204                                offset: px(6),
205                                color: Color::WHITE,
206                            },
207                            children![(
208                                Node {
209                                    width: px(10),
210                                    height: px(10),
211                                    ..default()
212                                },
213                                BorderRadius::MAX,
214                                BackgroundColor(YELLOW.into()),
215                            )],
216                        ),
217                        (Text::new(label), TextFont::from_font_size(9.0))
218                    ],
219                )
220            },
221        ))),
222    );
223
224    commands.spawn((
225        Node {
226            margin: UiRect::all(px(25)),
227            flex_direction: FlexDirection::Column,
228            align_self: AlignSelf::Stretch,
229            justify_self: JustifySelf::Stretch,
230            flex_wrap: FlexWrap::Wrap,
231            justify_content: JustifyContent::FlexStart,
232            align_items: AlignItems::FlexStart,
233            align_content: AlignContent::FlexStart,
234            ..default()
235        },
236        BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
237        children![
238            label("Borders"),
239            borders_examples,
240            label("Borders Rounded"),
241            borders_examples_rounded
242        ],
243    ));
244}
245
246// A label widget that accepts a &str and returns
247// a Bundle that can be spawned
248fn label(text: &str) -> impl Bundle {
249    (
250        Node {
251            margin: UiRect::all(px(25)),
252            ..default()
253        },
254        children![(Text::new(text), TextFont::from_font_size(20.0))],
255    )
256}