Skip to main content

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}