Skip to main content

system_fonts/
system_fonts.rs

1//! This example displays a scrollable list of all available system fonts.
2//! Demonstrates querying system fonts via `FontCx`.
3
4use bevy::{
5    diagnostic::FrameTimeDiagnosticsPlugin, input::mouse::MouseScrollUnit, prelude::*, text::FontCx,
6};
7
8fn main() {
9    let mut app = App::new();
10    app.add_plugins((DefaultPlugins, FrameTimeDiagnosticsPlugin::default()))
11        .add_systems(Startup, setup);
12
13    app.run();
14}
15
16fn setup(mut commands: Commands, mut font_system: ResMut<FontCx>) {
17    let mut families: Vec<String> = font_system
18        .context
19        .collection
20        .family_names()
21        .map(ToOwned::to_owned)
22        .collect();
23    families.sort_unstable();
24    families.dedup();
25    let family_count = families.len();
26
27    commands.spawn(Camera2d);
28
29    commands
30        .spawn((
31            Node {
32                flex_direction: FlexDirection::Column,
33                width: percent(100),
34                height: percent(100),
35                align_items: AlignItems::Center,
36                row_gap: px(10.),
37                ..default()
38            },
39            BackgroundColor(Color::srgb(0.1, 0.1, 0.1)),
40        ))
41        .with_children(move |builder| {
42            builder.spawn(Text::new(format!(
43                "Total available fonts: {}",
44                family_count,
45            )));
46
47            builder
48                .spawn(Node {
49                    flex_direction: FlexDirection::Column,
50                    row_gap: px(6),
51                    overflow: Overflow::scroll_y(),
52                    align_items: AlignItems::Stretch,
53                    ..default()
54                })
55                .with_children(|builder| {
56                    for family in families {
57                        let font = FontSource::Family(family.clone().into());
58                        builder.spawn((
59                            Node {
60                                display: Display::Grid,
61                                grid_template_columns: vec![
62                                    GridTrack::flex(1.),
63                                    GridTrack::flex(1.),
64                                ],
65                                padding: px(6).all(),
66                                column_gap: px(50.),
67                                ..default()
68                            },
69                            BackgroundColor(Color::srgb(0.2, 0.2, 0.25)),
70                            children![
71                                (
72                                    Text::new(&family),
73                                    TextFont { font, ..default() },
74                                    TextLayout::no_wrap()
75                                ),
76                                (Text::new(family), TextLayout::no_wrap()),
77                            ],
78                        ));
79                    }
80                })
81                .observe(
82                    |on_scroll: On<Pointer<Scroll>>,
83                     mut query: Query<(&mut ScrollPosition, &ComputedNode)>| {
84                        if let Ok((mut scroll_position, node)) = query.get_mut(on_scroll.entity) {
85                            let dy = match on_scroll.unit {
86                                MouseScrollUnit::Line => on_scroll.y * 20.,
87                                MouseScrollUnit::Pixel => on_scroll.y,
88                            };
89                            let range = (node.content_size.y - node.size.y).max(0.)
90                                * node.inverse_scale_factor;
91                            scroll_position.y = (scroll_position.y - dy).clamp(0., range);
92                        }
93                    },
94                );
95        });
96}