Skip to main content

fret_ui_kit/declarative/
global_watch.rs

1use std::any::Any;
2
3use fret_runtime::UiHost;
4use fret_ui::{ElementContext, Invalidation};
5
6/// Ergonomic helpers for observing-and-reading globals during declarative rendering.
7///
8/// This is intentionally a component-layer API (ADR 0066): it provides sugar on top of
9/// `fret-ui`'s explicit `observe_global(..., Invalidation)` contract.
10pub trait GlobalWatchExt {
11    type WatchedGlobal<'cx, T: Any>
12    where
13        Self: 'cx;
14
15    fn watch_global<'cx, T: Any>(&'cx mut self) -> Self::WatchedGlobal<'cx, T>;
16}
17
18impl<'a, H: UiHost> GlobalWatchExt for ElementContext<'a, H> {
19    type WatchedGlobal<'cx, T: Any>
20        = WatchedGlobal<'cx, 'a, H, T>
21    where
22        Self: 'cx;
23
24    fn watch_global<'cx, T: Any>(&'cx mut self) -> Self::WatchedGlobal<'cx, T> {
25        WatchedGlobal {
26            cx: self,
27            invalidation: Invalidation::Paint,
28            _ty: std::marker::PhantomData,
29        }
30    }
31}
32
33#[must_use]
34pub struct WatchedGlobal<'cx, 'a, H: UiHost, T: Any> {
35    cx: &'cx mut ElementContext<'a, H>,
36    invalidation: Invalidation,
37    _ty: std::marker::PhantomData<T>,
38}
39
40impl<'cx, 'a, H: UiHost, T: Any> WatchedGlobal<'cx, 'a, H, T> {
41    pub fn invalidation(mut self, invalidation: Invalidation) -> Self {
42        self.invalidation = invalidation;
43        self
44    }
45
46    pub fn paint(self) -> Self {
47        self.invalidation(Invalidation::Paint)
48    }
49
50    pub fn layout(self) -> Self {
51        self.invalidation(Invalidation::Layout)
52    }
53
54    pub fn hit_test(self) -> Self {
55        self.invalidation(Invalidation::HitTest)
56    }
57
58    pub fn observe(self) {
59        self.cx.observe_global::<T>(self.invalidation);
60    }
61
62    pub fn as_ref(self) -> Option<&'cx T> {
63        self.cx.observe_global::<T>(self.invalidation);
64        self.cx.app.global::<T>()
65    }
66
67    pub fn copied(self) -> Option<T>
68    where
69        T: Copy,
70    {
71        self.as_ref().copied()
72    }
73
74    pub fn cloned(self) -> Option<T>
75    where
76        T: Clone,
77    {
78        self.as_ref().cloned()
79    }
80
81    pub fn map<R>(self, f: impl FnOnce(&T) -> R) -> Option<R> {
82        self.as_ref().map(f)
83    }
84}