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 BorrowedContext<'a, 'w> = AppContext;
13 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
14 type Result<T> = Result<T>;
15
16 fn entity<T: Send + Sync + 'static>(
17 &mut self,
18 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
19 ) -> Self::Result<Handle<T>> {
20 let app = self
21 .0
22 .upgrade()
23 .ok_or_else(|| anyhow!("app was released"))?;
24 let mut lock = app.lock();
25 Ok(lock.entity(build_entity))
26 }
27
28 fn update_entity<T: Send + Sync + 'static, R>(
29 &mut self,
30 handle: &Handle<T>,
31 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
32 ) -> Self::Result<R> {
33 let app = self
34 .0
35 .upgrade()
36 .ok_or_else(|| anyhow!("app was released"))?;
37 let mut lock = app.lock();
38 Ok(lock.update_entity(handle, update))
39 }
40
41 fn read_global<G: 'static + Send + Sync, R>(
42 &self,
43 read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
44 ) -> Self::Result<R> {
45 let app = self
46 .0
47 .upgrade()
48 .ok_or_else(|| anyhow!("app was released"))?;
49 let mut lock = app.lock();
50 Ok(lock.read_global(read))
51 }
52}
53
54impl AsyncAppContext {
55 pub fn read_window<R>(
56 &self,
57 handle: AnyWindowHandle,
58 update: impl FnOnce(&WindowContext) -> R,
59 ) -> Result<R> {
60 let app = self
61 .0
62 .upgrade()
63 .ok_or_else(|| anyhow!("app was released"))?;
64 let mut app_context = app.lock();
65 app_context.read_window(handle.id, update)
66 }
67
68 pub fn update_window<R>(
69 &self,
70 handle: AnyWindowHandle,
71 update: impl FnOnce(&mut WindowContext) -> R,
72 ) -> Result<R> {
73 let app = self
74 .0
75 .upgrade()
76 .ok_or_else(|| anyhow!("app was released"))?;
77 let mut app_context = app.lock();
78 app_context.update_window(handle.id, update)
79 }
80}
81
82#[derive(Clone)]
83pub struct AsyncWindowContext {
84 app: AsyncAppContext,
85 window: AnyWindowHandle,
86}
87
88impl AsyncWindowContext {
89 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
90 Self { app, window }
91 }
92
93 pub fn update<R>(&self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
94 self.app.update_window(self.window, update)
95 }
96
97 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
98 self.app
99 .update_window(self.window, |cx| cx.on_next_frame(f))
100 .ok();
101 }
102}
103
104impl Context for AsyncWindowContext {
105 type BorrowedContext<'a, 'w> = WindowContext<'a, 'w>;
106 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
107 type Result<T> = Result<T>;
108
109 fn entity<R: Send + Sync + 'static>(
110 &mut self,
111 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
112 ) -> Result<Handle<R>> {
113 self.app
114 .update_window(self.window, |cx| cx.entity(build_entity))
115 }
116
117 fn update_entity<T: Send + Sync + 'static, R>(
118 &mut self,
119 handle: &Handle<T>,
120 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
121 ) -> Result<R> {
122 self.app
123 .update_window(self.window, |cx| cx.update_entity(handle, update))
124 }
125
126 fn read_global<G: 'static + Send + Sync, R>(
127 &self,
128 read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
129 ) -> Result<R> {
130 self.app.read_window(self.window, |cx| cx.read_global(read))
131 }
132}