vizia_core/
environment.rs1use crate::prelude::*;
3
4use unic_langid::LanguageIdentifier;
5use web_time::Duration;
6
7#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
9pub enum ThemeMode {
10 DarkMode,
12 #[default]
14 LightMode,
15}
16
17use crate::{context::EventContext, events::Event};
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21pub enum AppTheme {
22 System,
25 BuiltIn(ThemeMode),
27 }
29
30pub struct Theme {
32 pub app_theme: AppTheme,
34 pub sys_theme: Option<ThemeMode>,
36}
37
38impl Default for Theme {
39 fn default() -> Self {
40 Self { app_theme: AppTheme::BuiltIn(ThemeMode::LightMode), sys_theme: None }
41 }
42}
43
44impl Theme {
45 pub fn get_current_theme(&self) -> ThemeMode {
47 match self.app_theme {
48 AppTheme::System => self.sys_theme.unwrap_or_default(),
49 AppTheme::BuiltIn(theme) => theme,
50 }
51 }
52}
53
54pub struct Environment {
56 pub locale: Signal<LanguageIdentifier>,
58 pub theme: Theme,
60 pub(crate) caret_timer: Timer,
62}
63
64impl Environment {
65 pub(crate) fn new(cx: &mut Context) -> Self {
66 let locale: LanguageIdentifier =
67 sys_locale::get_locale().and_then(|l| l.parse().ok()).unwrap_or_default();
68 let caret_timer = cx.add_timer(Duration::from_millis(530), None, |cx, action| {
69 if matches!(action, TimerAction::Tick(_)) {
70 cx.emit(TextEvent::ToggleCaret);
71 }
72 });
73 Self { locale: Signal::new(locale.clone()), theme: Theme::default(), caret_timer }
74 }
75}
76
77pub enum EnvironmentEvent {
79 SetLocale(LanguageIdentifier),
81 SetThemeMode(AppTheme),
84 UseSystemLocale,
86 ToggleThemeMode,
88}
89
90impl Model for Environment {
91 fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
92 event.take(|event, _| match event {
93 EnvironmentEvent::SetLocale(locale) => {
94 self.locale.set(locale.clone());
95 }
96
97 EnvironmentEvent::SetThemeMode(theme) => {
98 theme.clone_into(&mut self.theme.app_theme);
99
100 cx.set_theme_mode(self.theme.get_current_theme());
101 cx.reload_styles().unwrap();
102 }
103
104 EnvironmentEvent::UseSystemLocale => {
105 self.locale
106 .set(sys_locale::get_locale().map(|l| l.parse().unwrap()).unwrap_or_default());
107 }
108
109 EnvironmentEvent::ToggleThemeMode => {
110 let theme_mode = match self.theme.get_current_theme() {
111 ThemeMode::DarkMode => ThemeMode::LightMode,
112 ThemeMode::LightMode => ThemeMode::DarkMode,
113 };
114
115 self.theme.app_theme = AppTheme::BuiltIn(theme_mode);
116
117 cx.set_theme_mode(theme_mode);
118 cx.reload_styles().unwrap();
119 }
120 });
121
122 event.map(|event, _| match event {
123 WindowEvent::ThemeChanged(theme) => {
124 self.theme.sys_theme = Some(*theme);
125 if self.theme.app_theme == AppTheme::System {
126 cx.set_theme_mode(*theme);
127 cx.reload_styles().unwrap();
128 }
129 }
130 _ => (),
131 })
132 }
133}