counter/
counter.rs

1#![allow(dead_code)]
2//! Simple counter.
3
4mod utils;
5use utils::*;
6
7use bevy::prelude::*;
8use haalka::prelude::*;
9
10fn main() {
11    App::new()
12        .add_plugins(examples_plugin)
13        .add_systems(
14            Startup,
15            (
16                |world: &mut World| {
17                    ui_root().spawn(world);
18                },
19                camera,
20            ),
21        )
22        .run();
23}
24
25#[derive(Component)]
26struct Counter(Mutable<i32>);
27
28fn ui_root() -> impl Element {
29    let counter = Mutable::new(0);
30    El::<Node>::new()
31        .with_node(|mut node| {
32            node.height = Val::Percent(100.);
33            node.width = Val::Percent(100.);
34        })
35        .cursor(CursorIcon::default())
36        .align_content(Align::center())
37        .child(
38            Row::<Node>::new()
39                .with_node(|mut node| node.column_gap = Val::Px(15.0))
40                .item(counter_button(counter.clone(), "-", -1))
41                .item(
42                    El::<Text>::new()
43                        .text_font(TextFont::from_font_size(25.))
44                        .text_signal(counter.signal_ref(ToString::to_string).map(Text)),
45                )
46                .item(counter_button(counter.clone(), "+", 1))
47                .update_raw_el(move |raw_el| raw_el.insert(Counter(counter))),
48        )
49}
50
51fn counter_button(counter: Mutable<i32>, label: &str, step: i32) -> impl Element {
52    let hovered = Mutable::new(false);
53    El::<Node>::new()
54        .with_node(|mut node| node.width = Val::Px(45.0))
55        .align_content(Align::center())
56        .border_radius(BorderRadius::MAX)
57        .cursor(CursorIcon::System(SystemCursorIcon::Pointer))
58        .background_color_signal(
59            hovered
60                .signal()
61                .map_bool(|| Color::hsl(300., 0.75, 0.85), || Color::hsl(300., 0.75, 0.75))
62                .map(BackgroundColor),
63        )
64        .hovered_sync(hovered)
65        .on_click(move || *counter.lock_mut() += step)
66        .child(
67            El::<Text>::new()
68                .text_font(TextFont::from_font_size(25.))
69                .text(Text::new(label)),
70        )
71}
72
73fn camera(mut commands: Commands) {
74    commands.spawn(Camera2d);
75}