Skip to main content

buttons/
buttons.rs

1use anathema::component::*;
2use anathema::prelude::*;
3
4struct App;
5
6#[derive(State)]
7struct AppState {
8    number: Value<i32>,
9}
10
11impl Component for App {
12    type Message = ();
13    type State = AppState;
14
15    const TICKS: bool = false;
16
17    fn on_event(
18        &mut self,
19        event: &mut UserEvent<'_>,
20        state: &mut Self::State,
21        _: Children<'_, '_>,
22        _: Context<'_, '_, Self::State>,
23    ) {
24        if event.name() == "increment" {
25            *state.number.to_mut() += 1;
26        } else if event.name() == "decrement" {
27            *state.number.to_mut() -= 1;
28        }
29    }
30
31    fn accept_focus(&self) -> bool {
32        false
33    }
34}
35
36struct Button;
37
38#[derive(State)]
39struct ButtonState {
40    active: Value<u8>,
41}
42
43impl Component for Button {
44    type Message = ();
45    type State = ButtonState;
46
47    const TICKS: bool = false;
48
49    fn on_blur(&mut self, state: &mut Self::State, _: Children<'_, '_>, _: Context<'_, '_, Self::State>) {
50        state.active.set(0);
51    }
52
53    fn on_focus(&mut self, state: &mut Self::State, _: Children<'_, '_>, _: Context<'_, '_, Self::State>) {
54        state.active.set(1);
55    }
56
57    fn on_mouse(
58        &mut self,
59        mouse: MouseEvent,
60        _: &mut Self::State,
61        mut children: Children<'_, '_>,
62        mut context: Context<'_, '_, Self::State>,
63    ) {
64        let pos = mouse.pos();
65        children.elements().at_position(pos).first(|_, _| {
66            if mouse.left_down() {
67                context.publish("click", ());
68
69                let id = context.attributes.get_as::<i64>("id").unwrap();
70                context.components.by_attribute("id", id).focus();
71            }
72        });
73    }
74
75    fn on_key(
76        &mut self,
77        key: KeyEvent,
78        _: &mut Self::State,
79        _: Children<'_, '_>,
80        mut context: Context<'_, '_, Self::State>,
81    ) {
82        if !matches!(key.state, KeyState::Press) {
83            return;
84        }
85
86        if let KeyCode::Enter = key.code {
87            context.publish("click", ());
88        }
89    }
90}
91
92fn main() {
93    let doc = Document::new("@main");
94
95    let mut backend = TuiBackend::builder()
96        .enable_alt_screen()
97        .enable_raw_mode()
98        .clear()
99        .hide_cursor()
100        .enable_mouse()
101        .finish()
102        .unwrap();
103    backend.finalize();
104
105    let mut builder = Runtime::builder(doc, &backend);
106
107    builder
108        .component(
109            "main",
110            "examples/templates/buttons/buttons.aml",
111            App,
112            AppState { number: 0.into() },
113        )
114        .unwrap();
115
116    builder
117        .prototype(
118            "button",
119            "examples/templates/buttons/button.aml",
120            || Button,
121            || ButtonState { active: 0.into() },
122        )
123        .unwrap();
124
125    builder
126        .finish(&mut backend, |runtime, backend| runtime.run(backend))
127        .unwrap();
128}