1use crate::{
2 AnyWindowHandle, AppContext, Context, Executor, Handle, MainThread, ModelContext, Result, Task,
3 ViewContext, WindowContext,
4};
5use anyhow::anyhow;
6use derive_more::{Deref, DerefMut};
7use parking_lot::Mutex;
8use std::{future::Future, sync::Weak};
9
10#[derive(Clone)]
11pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
12
13impl Context for AsyncAppContext {
14 type BorrowedContext<'a, 'w> = AppContext;
15 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
16 type Result<T> = Result<T>;
17
18 fn refresh(&mut self) -> Self::Result<()> {
19 let app = self
20 .0
21 .upgrade()
22 .ok_or_else(|| anyhow!("app was released"))?;
23 let mut lock = app.lock(); // Need this to compile
24 lock.refresh();
25 Ok(())
26 }
27
28 fn entity<T: Send + Sync + 'static>(
29 &mut self,
30 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
31 ) -> Self::Result<Handle<T>> {
32 let app = self
33 .0
34 .upgrade()
35 .ok_or_else(|| anyhow!("app was released"))?;
36 let mut lock = app.lock(); // Need this to compile
37 Ok(lock.entity(build_entity))
38 }
39
40 fn update_entity<T: Send + Sync + 'static, R>(
41 &mut self,
42 handle: &Handle<T>,
43 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> 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(); // Need this to compile
50 Ok(lock.update_entity(handle, update))
51 }
52
53 fn read_global<G: 'static + Send + Sync, R>(
54 &self,
55 read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
56 ) -> Self::Result<R> {
57 let app = self
58 .0
59 .upgrade()
60 .ok_or_else(|| anyhow!("app was released"))?;
61 let lock = app.lock(); // Need this to compile
62 Ok(lock.read_global(read))
63 }
64
65 fn update_global<G: 'static + Send + Sync, R>(
66 &mut self,
67 update: impl FnOnce(&mut G, &mut Self::BorrowedContext<'_, '_>) -> R,
68 ) -> Self::Result<R> {
69 let app = self
70 .0
71 .upgrade()
72 .ok_or_else(|| anyhow!("app was released"))?;
73 let mut lock = app.lock(); // Need this to compile
74 Ok(lock.update_global(update))
75 }
76}
77
78impl AsyncAppContext {
79 pub fn executor(&self) -> Result<Executor> {
80 let app = self
81 .0
82 .upgrade()
83 .ok_or_else(|| anyhow!("app was released"))?;
84 let lock = app.lock(); // Need this to compile
85 Ok(lock.executor().clone())
86 }
87
88 pub fn read_window<R>(
89 &self,
90 handle: AnyWindowHandle,
91 update: impl FnOnce(&WindowContext) -> R,
92 ) -> Result<R> {
93 let app = self
94 .0
95 .upgrade()
96 .ok_or_else(|| anyhow!("app was released"))?;
97 let mut app_context = app.lock();
98 app_context.read_window(handle.id, update)
99 }
100
101 pub fn update_window<R>(
102 &self,
103 handle: AnyWindowHandle,
104 update: impl FnOnce(&mut WindowContext) -> R,
105 ) -> Result<R> {
106 let app = self
107 .0
108 .upgrade()
109 .ok_or_else(|| anyhow!("app was released"))?;
110 let mut app_context = app.lock();
111 app_context.update_window(handle.id, update)
112 }
113
114 pub fn spawn<Fut, R>(
115 &self,
116 f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static,
117 ) -> Result<Task<R>>
118 where
119 Fut: Future<Output = R> + Send + 'static,
120 R: Send + 'static,
121 {
122 let app = self
123 .0
124 .upgrade()
125 .ok_or_else(|| anyhow!("app was released"))?;
126 let app_context = app.lock();
127 Ok(app_context.spawn(f))
128 }
129
130 pub fn run_on_main<R>(
131 &self,
132 f: impl FnOnce(&mut MainThread<AppContext>) -> R + Send + 'static,
133 ) -> Result<Task<R>>
134 where
135 R: Send + 'static,
136 {
137 let app = self
138 .0
139 .upgrade()
140 .ok_or_else(|| anyhow!("app was released"))?;
141 let mut app_context = app.lock();
142 Ok(app_context.run_on_main(f))
143 }
144}
145
146#[derive(Clone, Deref, DerefMut)]
147pub struct AsyncWindowContext {
148 #[deref]
149 #[deref_mut]
150 app: AsyncAppContext,
151 window: AnyWindowHandle,
152}
153
154impl AsyncWindowContext {
155 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
156 Self { app, window }
157 }
158
159 pub fn update<R>(&self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
160 self.app.update_window(self.window, update)
161 }
162
163 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
164 self.app
165 .update_window(self.window, |cx| cx.on_next_frame(f))
166 .ok();
167 }
168}
169
170impl Context for AsyncWindowContext {
171 type BorrowedContext<'a, 'w> = WindowContext<'a, 'w>;
172 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
173 type Result<T> = Result<T>;
174
175 fn refresh(&mut self) -> Self::Result<()> {
176 self.app.refresh()
177 }
178
179 fn entity<R: Send + Sync + 'static>(
180 &mut self,
181 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
182 ) -> Result<Handle<R>> {
183 self.app
184 .update_window(self.window, |cx| cx.entity(build_entity))
185 }
186
187 fn update_entity<T: Send + Sync + 'static, R>(
188 &mut self,
189 handle: &Handle<T>,
190 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
191 ) -> Result<R> {
192 self.app
193 .update_window(self.window, |cx| cx.update_entity(handle, update))
194 }
195
196 fn read_global<G: 'static + Send + Sync, R>(
197 &self,
198 read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
199 ) -> Result<R> {
200 self.app.read_window(self.window, |cx| cx.read_global(read))
201 }
202
203 fn update_global<G: 'static + Send + Sync, R>(
204 &mut self,
205 update: impl FnOnce(&mut G, &mut Self::BorrowedContext<'_, '_>) -> R,
206 ) -> Result<R> {
207 self.app
208 .update_window(self.window, |cx| cx.update_global(update))
209 }
210}