1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Rust-side theme helpers for Neon's dark/light switch.
//!
//! Slint can't auto-impl a Rust trait on its generated globals, so
//! these helpers are duck-typed via macros — they work with any
//! window+theme pair from a consumer's `slint::include_modules!()`.
//!
//! For a one-shot setup (instantiate window + apply initial theme)
//! see [`crate::neon_ui_setup!`]. The functions here are for
//! *runtime* theme changes (e.g. a Settings toggle).
//!
//! ## Why functions and not a trait
//!
//! A trait `ThemeBridge` would require `impl ThemeBridge for
//! ConsumerWindow` boilerplate in every consuming app. Two
//! one-line macros wrap the call instead — same ergonomics,
//! zero per-app boilerplate.
//!
//! ## Usage
//!
//! ```ignore
//! use slint::ComponentHandle;
//! use slint_ui_system::theme;
//! slint::include_modules!();
//!
//! let win = AppWindow::new()?;
//! theme::set_dark_mode(&win, false); // light
//! assert!(!theme::is_dark_mode(&win));
//! ```
/// Set Neon's dark/light flag on a window.
///
/// Looks up the `Theme` global on `window` and calls
/// `set_dark_mode(dark)`. The `Theme` global is generated by
/// `slint::include_modules!()` in the caller's crate when their
/// `.slint` imports `@neon`.
///
/// # Panics
///
/// Panics if `window` doesn't have the `Theme` global. That only
/// happens when the consumer forgot to import Neon's components
/// in their `.slint` — a programmer error, not a runtime
/// condition.
///
/// # Example
///
/// ```ignore
/// use slint_ui_system::theme;
/// theme::set_dark_mode(&win, true);
/// ```
/// Read Neon's current dark/light flag.
/// Flip the current theme (dark ↔ light).
///
/// Convenience for "Settings → Toggle theme" buttons. Equivalent
/// to `set_dark_mode(window, !is_dark_mode(window))`.
// ── ThemeAccess trait ───────────────────────────────────────────────
/// Trait that the consumer's window type implements to wire up
/// Neon's theme helpers. The implementation is one line per method
/// — the [`impl_theme_access!`](crate::impl_theme_access) macro
/// generates it for you.
///
/// ```ignore
/// use slint_ui_system::theme::impl_theme_access;
/// slint::include_modules!();
///
/// impl_theme_access!(AppWindow, Theme);
/// ```
///
/// After that the consumer can call `theme::set_dark_mode`,
/// `theme::is_dark_mode`, and `theme::toggle` on `AppWindow`.
/// Implement [`ThemeAccess`] for a consumer's window type, wiring
/// it through to a Slint-generated `Theme` global.
///
/// ## Arguments
///
/// 1. `$window` — the window type generated by
/// `slint::include_modules!()`, e.g. `AppWindow`.
/// 2. `$theme` — the theme global type generated alongside,
/// typically `Theme`.
///
/// ## Example
///
/// ```ignore
/// use slint_ui_system::impl_theme_access;
/// slint::include_modules!(); // gives us `AppWindow` + `Theme`
/// impl_theme_access!(AppWindow, Theme);
/// ```