maycoon_core/app/
context.rs

1use crate::app::diagnostics::Diagnostics;
2use crate::app::update::{Update, UpdateManager};
3use crate::signal::Signal;
4use crate::signal::eval::EvalSignal;
5use crate::signal::fixed::FixedSignal;
6use crate::signal::memoized::MemoizedSignal;
7use crate::signal::state::StateSignal;
8
9/// The application context for managing the application lifecycle.
10#[derive(Clone)]
11pub struct AppContext {
12    update: UpdateManager,
13    diagnostics: Diagnostics,
14}
15
16impl AppContext {
17    /// Create a new application context using the given [UpdateManager].
18    #[inline(always)]
19    #[tracing::instrument(level = "trace", skip_all)]
20    pub fn new(update: UpdateManager, diagnostics: Diagnostics) -> Self {
21        Self {
22            update,
23            diagnostics,
24        }
25    }
26
27    /// Get the [Diagnostics] of the application.
28    #[inline(always)]
29    pub const fn diagnostics(&self) -> Diagnostics {
30        self.diagnostics
31    }
32
33    /// Get the [UpdateManager] of the application.
34    #[inline(always)]
35    pub fn update(&self) -> UpdateManager {
36        self.update.clone()
37    }
38
39    /// Make the application exit by setting [Update::EXIT].
40    #[inline(always)]
41    pub fn exit(&self) {
42        self.update.insert(Update::EXIT);
43    }
44
45    /// Hook the given [Signal] to the [UpdateManager] of this application and return it.
46    ///
47    /// This makes the signal reactive, so it will notify the renderer when the inner value changes.
48    #[inline(always)]
49    pub fn use_signal<T: 'static, S: Signal<T>>(&self, signal: S) -> S {
50        let update = self.update();
51
52        signal.listen(Box::new(move |_| update.insert(Update::EVAL)))
53    }
54
55    /// Shortcut for creating and hooking a [StateSignal] into the application lifecycle.
56    #[inline(always)]
57    pub fn use_state<T: 'static>(&self, value: T) -> StateSignal<T> {
58        self.use_signal(StateSignal::new(value))
59    }
60
61    /// Shortcut for creating and hooking a [MemoizedSignal] into the application lifecycle.
62    #[inline(always)]
63    pub fn use_memoized<T: 'static>(&self, value: impl Fn() -> T + 'static) -> MemoizedSignal<T> {
64        self.use_signal(MemoizedSignal::new(value))
65    }
66
67    /// Shortcut for creating and hooking a [FixedSignal] into the application lifecycle.
68    #[inline(always)]
69    pub fn use_fixed<T: 'static>(&self, value: T) -> FixedSignal<T> {
70        self.use_signal(FixedSignal::new(value))
71    }
72
73    /// Shortcut for creating and hooking an [EvalSignal] into the application lifecycle.
74    #[inline(always)]
75    pub fn use_eval<T: 'static>(&self, eval: impl Fn() -> T + 'static) -> EvalSignal<T> {
76        self.use_signal(EvalSignal::new(eval))
77    }
78}