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}