global.rs

 1use crate::{App, BorrowAppContext};
 2
 3/// A marker trait for types that can be stored in GPUI's global state.
 4///
 5/// This trait exists to provide type-safe access to globals by ensuring only
 6/// types that implement [`Global`] can be used with the accessor methods. For
 7/// example, trying to access a global with a type that does not implement
 8/// [`Global`] will result in a compile-time error.
 9///
10/// Implement this on types you want to store in the context as a global.
11///
12/// ## Restricting Access to Globals
13///
14/// In some situations you may need to store some global state, but want to
15/// restrict access to reading it or writing to it.
16///
17/// In these cases, Rust's visibility system can be used to restrict access to
18/// a global value. For example, you can create a private struct that implements
19/// [`Global`] and holds the global state. Then create a newtype struct that wraps
20/// the global type and create custom accessor methods to expose the desired subset
21/// of operations.
22pub trait Global: 'static {
23    // This trait is intentionally left empty, by virtue of being a marker trait.
24    //
25    // Use additional traits with blanket implementations to attach functionality
26    // to types that implement `Global`.
27}
28
29/// A trait for reading a global value from the context.
30pub trait ReadGlobal {
31    /// Returns the global instance of the implementing type.
32    ///
33    /// Panics if a global for that type has not been assigned.
34    fn global(cx: &App) -> &Self;
35}
36
37impl<T: Global> ReadGlobal for T {
38    fn global(cx: &App) -> &Self {
39        cx.global::<T>()
40    }
41}
42
43/// A trait for updating a global value in the context.
44pub trait UpdateGlobal {
45    /// Updates the global instance of the implementing type using the provided closure.
46    ///
47    /// This method provides the closure with mutable access to the context and the global simultaneously.
48    fn update_global<C, F, R>(cx: &mut C, update: F) -> R
49    where
50        C: BorrowAppContext,
51        F: FnOnce(&mut Self, &mut C) -> R;
52
53    /// Set the global instance of the implementing type.
54    fn set_global<C>(cx: &mut C, global: Self)
55    where
56        C: BorrowAppContext;
57}
58
59impl<T: Global> UpdateGlobal for T {
60    #[track_caller]
61    fn update_global<C, F, R>(cx: &mut C, update: F) -> R
62    where
63        C: BorrowAppContext,
64        F: FnOnce(&mut Self, &mut C) -> R,
65    {
66        cx.update_global(update)
67    }
68
69    fn set_global<C>(cx: &mut C, global: Self)
70    where
71        C: BorrowAppContext,
72    {
73        cx.set_global(global)
74    }
75}