async_context.rs

 1use crate::{
 2    AnyWindowHandle, AppContext, Context, Handle, ModelContext, Result, ViewContext, WindowContext,
 3};
 4use anyhow::anyhow;
 5use parking_lot::Mutex;
 6use std::sync::Weak;
 7
 8#[derive(Clone)]
 9pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
10
11impl Context for AsyncAppContext {
12    type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
13    type Result<T> = Result<T>;
14
15    fn entity<T: Send + Sync + 'static>(
16        &mut self,
17        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
18    ) -> Result<Handle<T>> {
19        let app = self
20            .0
21            .upgrade()
22            .ok_or_else(|| anyhow!("app was released"))?;
23        let mut lock = app.lock(); // Does not compile without this variable.
24        Ok(lock.entity(build_entity))
25    }
26
27    fn update_entity<T: Send + Sync + 'static, R>(
28        &mut self,
29        handle: &Handle<T>,
30        update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
31    ) -> Result<R> {
32        let app = self
33            .0
34            .upgrade()
35            .ok_or_else(|| anyhow!("app was released"))?;
36        let mut lock = app.lock(); // Does not compile without this variable.
37        Ok(lock.update_entity(handle, update))
38    }
39}
40
41impl AsyncAppContext {
42    pub fn update_window<R>(
43        &self,
44        handle: AnyWindowHandle,
45        update: impl FnOnce(&mut WindowContext) -> R,
46    ) -> Result<R> {
47        let app = self
48            .0
49            .upgrade()
50            .ok_or_else(|| anyhow!("app was released"))?;
51        let mut app_context = app.lock();
52        app_context.update_window(handle.id, update)
53    }
54}
55
56#[derive(Clone)]
57pub struct AsyncWindowContext {
58    app: AsyncAppContext,
59    window: AnyWindowHandle,
60}
61
62impl AsyncWindowContext {
63    pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
64        Self { app, window }
65    }
66
67    pub fn update<R>(&self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
68        self.app.update_window(self.window, update)
69    }
70
71    pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
72        self.app
73            .update_window(self.window, |cx| cx.on_next_frame(f))
74            .ok();
75    }
76}
77
78impl Context for AsyncWindowContext {
79    type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
80    type Result<T> = Result<T>;
81
82    fn entity<R: Send + Sync + 'static>(
83        &mut self,
84        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
85    ) -> Result<Handle<R>> {
86        self.app
87            .update_window(self.window, |cx| cx.entity(build_entity))
88    }
89
90    fn update_entity<T: Send + Sync + 'static, R>(
91        &mut self,
92        handle: &Handle<T>,
93        update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
94    ) -> Result<R> {
95        self.app
96            .update_window(self.window, |cx| cx.update_entity(handle, update))
97    }
98}