gioser

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 660Markdown 302TOML 157RON 312382 Sutichaykuna

⎇ main widgets/theme-switcher/examples/theme_switcher_demo.rs Rust · 153 siq'ikuna · 4.3 KB Ñawpa willay Pi imata llamkarqan ch'uya

chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros d251eb32b · Sergio ·

1//! Showcase de `llimphi-widget-theme-switcher`.
2//!
3//! Una ventana con el switcher en la cabecera + un sample de paneles
4//! que cambian de color al ciclar. Validación visual de que el theme
5//! propaga a la UI: al hacer click en el switcher, los paneles se
6//! repintan con el siguiente preset.
7//!
8//! Corre: `cargo run -p llimphi-widget-theme-switcher --example theme_switcher_demo --release`.
9
10use llimphi_theme::Theme;
11use llimphi_ui::llimphi_layout::taffy::{
12    prelude::{length, percent, AlignItems, FlexDirection, JustifyContent, Size, Style},
13    Rect,
14};
15use llimphi_ui::llimphi_text::Alignment;
16use llimphi_ui::{App, Handle, View};
17use llimphi_widget_theme_switcher::theme_switcher_view;
18
19#[derive(Clone, Debug)]
20enum Msg {
21    ChangeTheme(Theme),
22}
23
24struct Model {
25    theme: Theme,
26}
27
28struct Showcase;
29
30impl App for Showcase {
31    type Model = Model;
32    type Msg = Msg;
33
34    fn title() -> &'static str {
35        "llimphi · theme-switcher"
36    }
37
38    fn init(_: &Handle<Msg>) -> Model {
39        Model {
40            theme: Theme::dark(),
41        }
42    }
43
44    fn update(model: Model, msg: Msg, _: &Handle<Msg>) -> Model {
45        let mut m = model;
46        match msg {
47            Msg::ChangeTheme(t) => m.theme = t,
48        }
49        m
50    }
51
52    fn view(model: &Model) -> View<Msg> {
53        let switcher = theme_switcher_view(&model.theme, Msg::ChangeTheme);
54
55        let header = View::new(Style {
56            size: Size {
57                width: percent(1.0_f32),
58                height: length(48.0_f32),
59            },
60            flex_direction: FlexDirection::Row,
61            align_items: Some(AlignItems::CENTER),
62            justify_content: Some(JustifyContent::SPACE_BETWEEN),
63            padding: Rect {
64                left: length(16.0_f32),
65                right: length(16.0_f32),
66                top: length(0.0_f32),
67                bottom: length(0.0_f32),
68            },
69            ..Default::default()
70        })
71        .fill(model.theme.bg_panel)
72        .children(vec![
73            View::new(Style {
74                size: Size {
75                    width: length(220.0_f32),
76                    height: length(32.0_f32),
77                },
78                ..Default::default()
79            })
80            .text_aligned(
81                format!("Preset actual: {}", model.theme.name),
82                13.0,
83                model.theme.fg_text,
84                Alignment::Start,
85            ),
86            switcher,
87        ]);
88
89        let card_a = sample_card("Panel principal", &model.theme, model.theme.bg_panel);
90        let card_b = sample_card(
91            "Strip alternativo",
92            &model.theme,
93            model.theme.bg_panel_alt,
94        );
95        let card_c = sample_card("Input focado", &model.theme, model.theme.bg_input_focus);
96
97        let body = View::new(Style {
98            flex_direction: FlexDirection::Column,
99            size: Size {
100                width: percent(1.0_f32),
101                height: percent(1.0_f32),
102            },
103            padding: Rect {
104                left: length(24.0_f32),
105                right: length(24.0_f32),
106                top: length(24.0_f32),
107                bottom: length(24.0_f32),
108            },
109            gap: Size {
110                width: length(0.0_f32),
111                height: length(14.0_f32),
112            },
113            ..Default::default()
114        })
115        .fill(model.theme.bg_app)
116        .children(vec![card_a, card_b, card_c]);
117
118        View::new(Style {
119            flex_direction: FlexDirection::Column,
120            size: Size {
121                width: percent(1.0_f32),
122                height: percent(1.0_f32),
123            },
124            ..Default::default()
125        })
126        .fill(model.theme.bg_app)
127        .children(vec![header, body])
128    }
129}
130
131fn sample_card(label: &str, theme: &Theme, bg: llimphi_ui::llimphi_raster::peniko::Color) -> View<Msg> {
132    View::new(Style {
133        size: Size {
134            width: percent(1.0_f32),
135            height: length(60.0_f32),
136        },
137        padding: Rect {
138            left: length(14.0_f32),
139            right: length(14.0_f32),
140            top: length(0.0_f32),
141            bottom: length(0.0_f32),
142        },
143        align_items: Some(AlignItems::CENTER),
144        ..Default::default()
145    })
146    .fill(bg)
147    .radius(6.0)
148    .text_aligned(label.to_string(), 13.0, theme.fg_text, Alignment::Start)
149}
150
151fn main() {
152    llimphi_ui::run::<Showcase>();
153}