Skip to main content

counter/
counter.rs

1//! Fase 4 de Llimphi: contador Elm puro con texto real.
2//!
3//! Bucle completo input→update→view→layout→raster→present. El click sobre
4//! el botón inferior incrementa el contador; el panel central muestra el
5//! número actual rasterizado por skrifa+vello.
6//!
7//! Corre con: `cargo run -p llimphi-ui --example counter --release`.
8
9use llimphi_ui::llimphi_layout::taffy::{
10    prelude::{length, percent, Dimension, FlexDirection, Size, Style},
11    AlignItems, JustifyContent,
12};
13use llimphi_ui::llimphi_raster::peniko::Color;
14use llimphi_ui::{App, Handle, View};
15
16#[derive(Clone)]
17enum Msg {
18    Increment,
19    Reset,
20}
21
22struct Counter;
23
24impl App for Counter {
25    type Model = u32;
26    type Msg = Msg;
27
28    fn title() -> &'static str {
29        "llimphi · counter"
30    }
31
32    fn init(_: &Handle<Self::Msg>) -> Self::Model {
33        0
34    }
35
36    fn update(model: Self::Model, msg: Self::Msg, _: &Handle<Self::Msg>) -> Self::Model {
37        match msg {
38            Msg::Increment => model.saturating_add(1),
39            Msg::Reset => 0,
40        }
41    }
42
43    fn view(model: &Self::Model) -> View<Self::Msg> {
44        let number = View::new(Style {
45            size: Size {
46                width: percent(1.0_f32),
47                height: Dimension::auto(),
48            },
49            flex_grow: 1.0,
50            align_items: Some(AlignItems::Center),
51            justify_content: Some(JustifyContent::Center),
52            ..Default::default()
53        })
54        .text(model.to_string(), 160.0, Color::from_rgba8(230, 240, 250, 255));
55
56        let increment = View::new(Style {
57            size: Size {
58                width: length(160.0_f32),
59                height: length(56.0_f32),
60            },
61            align_items: Some(AlignItems::Center),
62            justify_content: Some(JustifyContent::Center),
63            ..Default::default()
64        })
65        .fill(Color::from_rgba8(60, 200, 130, 255))
66        .radius(12.0)
67        .text("+1", 28.0, Color::from_rgba8(10, 30, 20, 255))
68        .on_click(Msg::Increment);
69
70        let reset = View::new(Style {
71            size: Size {
72                width: length(120.0_f32),
73                height: length(56.0_f32),
74            },
75            align_items: Some(AlignItems::Center),
76            justify_content: Some(JustifyContent::Center),
77            ..Default::default()
78        })
79        .fill(Color::from_rgba8(220, 80, 80, 255))
80        .radius(12.0)
81        .text("reset", 22.0, Color::from_rgba8(30, 10, 10, 255))
82        .on_click(Msg::Reset);
83
84        let buttons = View::new(Style {
85            flex_direction: FlexDirection::Row,
86            size: Size {
87                width: percent(1.0_f32),
88                height: length(56.0_f32),
89            },
90            gap: Size {
91                width: length(16.0_f32),
92                height: length(0.0_f32),
93            },
94            justify_content: Some(JustifyContent::Center),
95            ..Default::default()
96        })
97        .children(vec![increment, reset]);
98
99        View::new(Style {
100            flex_direction: FlexDirection::Column,
101            size: Size {
102                width: percent(1.0_f32),
103                height: percent(1.0_f32),
104            },
105            gap: Size {
106                width: length(0.0_f32),
107                height: length(24.0_f32),
108            },
109            padding: llimphi_ui::llimphi_layout::taffy::Rect {
110                left: length(32.0_f32),
111                right: length(32.0_f32),
112                top: length(32.0_f32),
113                bottom: length(32.0_f32),
114            },
115            ..Default::default()
116        })
117        .fill(Color::from_rgba8(20, 24, 32, 255))
118        .children(vec![number, buttons])
119    }
120}
121
122fn main() {
123    llimphi_ui::run::<Counter>();
124}