freya_core/platform.rs
1use std::{
2 borrow::Cow,
3 rc::Rc,
4};
5
6use bytes::Bytes;
7pub use mundy::{
8 AccentColor,
9 Srgba,
10};
11use torin::prelude::Size2D;
12
13use crate::{
14 accessibility::id::AccessibilityId,
15 prelude::{
16 State,
17 consume_root_context,
18 },
19 user_event::UserEvent,
20};
21
22#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Hash)]
23pub enum NavigationMode {
24 #[default]
25 NotKeyboard,
26 Keyboard,
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
30pub enum PreferredTheme {
31 #[default]
32 Light,
33 Dark,
34}
35
36/// Access point to different Freya-managed states such as the focused node,
37/// root window size, navigation mode, and theme preference.
38///
39/// Retrieve it from any component with [`Platform::get`].
40#[derive(Clone)]
41pub struct Platform {
42 /// The [`AccessibilityId`] of the currently focused node.
43 pub focused_accessibility_id: State<AccessibilityId>,
44 /// The accessibility node data of the currently focused node.
45 pub focused_accessibility_node: State<accesskit::Node>,
46 /// The size of the root window.
47 pub root_size: State<Size2D>,
48 /// Rendering scale factor, the OS scale factor multiplied by the custom scale factor.
49 pub scale_factor: State<f64>,
50 /// Custom scale factor, change it with [`Platform::set_custom_scale_factor`].
51 pub custom_scale_factor: State<f64>,
52 /// The current [`NavigationMode`].
53 pub navigation_mode: State<NavigationMode>,
54 /// The OS-level [`PreferredTheme`].
55 pub preferred_theme: State<PreferredTheme>,
56 /// Whether the app currently has the OS-level focus.
57 pub is_app_focused: State<bool>,
58 /// The OS-level [`AccentColor`].
59 pub accent_color: State<AccentColor>,
60 /// Sender used to dispatch [`UserEvent`]s to the active renderer.
61 pub sender: Rc<dyn Fn(UserEvent)>,
62}
63
64impl Platform {
65 /// Retrieve the [`Platform`] from the root context.
66 #[track_caller]
67 pub fn get() -> Self {
68 consume_root_context()
69 }
70
71 /// Dispatch a [`UserEvent`] to the active renderer.
72 pub fn send(&self, event: UserEvent) {
73 (self.sender)(event)
74 }
75
76 /// Request the renderer to use a custom scale factor, multiplied with the
77 /// OS scale factor. The value might get clamped to a reasonable range.
78 pub fn set_custom_scale_factor(&self, custom_scale_factor: f64) {
79 self.send(UserEvent::SetCustomScaleFactor(custom_scale_factor));
80 }
81
82 /// Load a font at runtime, making it available under the given name in all windows.
83 ///
84 /// # Example
85 ///
86 /// ```rust,no_run
87 /// use freya_core::prelude::*;
88 ///
89 /// fn load_rubik() {
90 /// let font = std::fs::read("./Rubik.ttf").expect("Failed to read the font file.");
91 /// Platform::get().load_font("Rubik", font);
92 /// }
93 /// ```
94 pub fn load_font(&self, font_name: impl Into<Cow<'static, str>>, font_data: impl Into<Bytes>) {
95 self.send(UserEvent::LoadFont {
96 font_name: font_name.into(),
97 font_data: font_data.into(),
98 });
99 }
100}