1use crate::{
2 AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, ForegroundExecutor,
3 Model, ModelContext, Render, Result, Task, View, ViewContext, VisualContext, WindowContext,
4 WindowHandle,
5};
6use anyhow::{anyhow, Context as _};
7use derive_more::{Deref, DerefMut};
8use std::{future::Future, rc::Weak};
9
10#[derive(Clone)]
11pub struct AsyncAppContext {
12 pub(crate) app: Weak<AppCell>,
13 pub(crate) background_executor: BackgroundExecutor,
14 pub(crate) foreground_executor: ForegroundExecutor,
15}
16
17impl Context for AsyncAppContext {
18 type Result<T> = Result<T>;
19
20 fn build_model<T: 'static>(
21 &mut self,
22 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
23 ) -> Self::Result<Model<T>>
24 where
25 T: 'static,
26 {
27 let app = self
28 .app
29 .upgrade()
30 .ok_or_else(|| anyhow!("app was released"))?;
31 let mut app = app.borrow_mut();
32 Ok(app.build_model(build_model))
33 }
34
35 fn update_model<T: 'static, R>(
36 &mut self,
37 handle: &Model<T>,
38 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
39 ) -> Self::Result<R> {
40 let app = self
41 .app
42 .upgrade()
43 .ok_or_else(|| anyhow!("app was released"))?;
44 let mut app = app.borrow_mut();
45 Ok(app.update_model(handle, update))
46 }
47
48 fn read_model<T, R>(
49 &self,
50 handle: &Model<T>,
51 callback: impl FnOnce(&T, &AppContext) -> R,
52 ) -> Self::Result<R>
53 where
54 T: 'static,
55 {
56 let app = self.app.upgrade().context("app was released")?;
57 let lock = app.borrow();
58 Ok(lock.read_model(handle, callback))
59 }
60
61 fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
62 where
63 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
64 {
65 let app = self.app.upgrade().context("app was released")?;
66 let mut lock = app.borrow_mut();
67 lock.update_window(window, f)
68 }
69
70 fn read_window<R>(
71 &self,
72 window: &AnyWindowHandle,
73 read: impl FnOnce(AnyView, &AppContext) -> R,
74 ) -> Result<R> {
75 let app = self.app.upgrade().context("app was released")?;
76 let lock = app.borrow();
77 lock.read_window(window, read)
78 }
79}
80
81impl AsyncAppContext {
82 pub fn refresh(&mut self) -> Result<()> {
83 let app = self
84 .app
85 .upgrade()
86 .ok_or_else(|| anyhow!("app was released"))?;
87 let mut lock = app.borrow_mut();
88 lock.refresh();
89 Ok(())
90 }
91
92 pub fn background_executor(&self) -> &BackgroundExecutor {
93 &self.background_executor
94 }
95
96 pub fn foreground_executor(&self) -> &ForegroundExecutor {
97 &self.foreground_executor
98 }
99
100 pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
101 let app = self
102 .app
103 .upgrade()
104 .ok_or_else(|| anyhow!("app was released"))?;
105 let mut lock = app.borrow_mut();
106 Ok(f(&mut *lock))
107 }
108
109 pub fn open_window<V>(
110 &self,
111 options: crate::WindowOptions,
112 build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
113 ) -> Result<WindowHandle<V>>
114 where
115 V: Render,
116 {
117 let app = self
118 .app
119 .upgrade()
120 .ok_or_else(|| anyhow!("app was released"))?;
121 let mut lock = app.borrow_mut();
122 Ok(lock.open_window(options, build_root_view))
123 }
124
125 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
126 where
127 Fut: Future<Output = R> + 'static,
128 R: 'static,
129 {
130 self.foreground_executor.spawn(f(self.clone()))
131 }
132
133 pub fn has_global<G: 'static>(&self) -> Result<bool> {
134 let app = self
135 .app
136 .upgrade()
137 .ok_or_else(|| anyhow!("app was released"))?;
138 let app = app.borrow_mut();
139 Ok(app.has_global::<G>())
140 }
141
142 pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
143 let app = self
144 .app
145 .upgrade()
146 .ok_or_else(|| anyhow!("app was released"))?;
147 let app = app.borrow_mut();
148 Ok(read(app.global(), &app))
149 }
150
151 pub fn try_read_global<G: 'static, R>(
152 &self,
153 read: impl FnOnce(&G, &AppContext) -> R,
154 ) -> Option<R> {
155 let app = self.app.upgrade()?;
156 let app = app.borrow_mut();
157 Some(read(app.try_global()?, &app))
158 }
159
160 pub fn update_global<G: 'static, R>(
161 &mut self,
162 update: impl FnOnce(&mut G, &mut AppContext) -> R,
163 ) -> Result<R> {
164 let app = self
165 .app
166 .upgrade()
167 .ok_or_else(|| anyhow!("app was released"))?;
168 let mut app = app.borrow_mut();
169 Ok(app.update_global(update))
170 }
171}
172
173#[derive(Clone, Deref, DerefMut)]
174pub struct AsyncWindowContext {
175 #[deref]
176 #[deref_mut]
177 app: AsyncAppContext,
178 window: AnyWindowHandle,
179}
180
181impl AsyncWindowContext {
182 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
183 Self { app, window }
184 }
185
186 pub fn update<R>(
187 &mut self,
188 update: impl FnOnce(AnyView, &mut WindowContext) -> R,
189 ) -> Result<R> {
190 self.app.update_window(self.window, update)
191 }
192
193 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
194 self.window.update(self, |_, cx| cx.on_next_frame(f)).ok();
195 }
196
197 pub fn read_global<G: 'static, R>(
198 &mut self,
199 read: impl FnOnce(&G, &WindowContext) -> R,
200 ) -> Result<R> {
201 self.window.update(self, |_, cx| read(cx.global(), cx))
202 }
203
204 pub fn update_global<G, R>(
205 &mut self,
206 update: impl FnOnce(&mut G, &mut WindowContext) -> R,
207 ) -> Result<R>
208 where
209 G: 'static,
210 {
211 self.window.update(self, |_, cx| cx.update_global(update))
212 }
213
214 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncWindowContext) -> Fut) -> Task<R>
215 where
216 Fut: Future<Output = R> + 'static,
217 R: 'static,
218 {
219 self.foreground_executor.spawn(f(self.clone()))
220 }
221}
222
223impl Context for AsyncWindowContext {
224 type Result<T> = Result<T>;
225
226 fn build_model<T>(
227 &mut self,
228 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
229 ) -> Result<Model<T>>
230 where
231 T: 'static,
232 {
233 self.window
234 .update(self, |_, cx| cx.build_model(build_model))
235 }
236
237 fn update_model<T: 'static, R>(
238 &mut self,
239 handle: &Model<T>,
240 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
241 ) -> Result<R> {
242 self.window
243 .update(self, |_, cx| cx.update_model(handle, update))
244 }
245
246 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
247 where
248 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
249 {
250 self.app.update_window(window, update)
251 }
252
253 fn read_model<T, R>(
254 &self,
255 handle: &Model<T>,
256 read: impl FnOnce(&T, &AppContext) -> R,
257 ) -> Self::Result<R>
258 where
259 T: 'static,
260 {
261 self.app.read_model(handle, read)
262 }
263
264 fn read_window<R>(
265 &self,
266 window: &AnyWindowHandle,
267 read: impl FnOnce(AnyView, &AppContext) -> R,
268 ) -> Result<R> {
269 self.app.read_window(window, read)
270 }
271}
272
273impl VisualContext for AsyncWindowContext {
274 fn build_view<V>(
275 &mut self,
276 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
277 ) -> Self::Result<View<V>>
278 where
279 V: 'static + Render,
280 {
281 self.window
282 .update(self, |_, cx| cx.build_view(build_view_state))
283 }
284
285 fn update_view<V: 'static, R>(
286 &mut self,
287 view: &View<V>,
288 update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
289 ) -> Self::Result<R> {
290 self.window
291 .update(self, |_, cx| cx.update_view(view, update))
292 }
293
294 fn replace_root_view<V>(
295 &mut self,
296 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
297 ) -> Self::Result<View<V>>
298 where
299 V: Render,
300 {
301 self.window
302 .update(self, |_, cx| cx.replace_root_view(build_view))
303 }
304}