1use crate::{
2 AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, DismissEvent,
3 FocusableView, ForegroundExecutor, Model, ModelContext, Render, Result, Task, View,
4 ViewContext, VisualContext, WindowContext, 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<T, R>(
71 &self,
72 window: &WindowHandle<T>,
73 read: impl FnOnce(View<T>, &AppContext) -> R,
74 ) -> Result<R>
75 where
76 T: 'static,
77 {
78 let app = self.app.upgrade().context("app was released")?;
79 let lock = app.borrow();
80 lock.read_window(window, read)
81 }
82}
83
84impl AsyncAppContext {
85 pub fn refresh(&mut self) -> Result<()> {
86 let app = self
87 .app
88 .upgrade()
89 .ok_or_else(|| anyhow!("app was released"))?;
90 let mut lock = app.borrow_mut();
91 lock.refresh();
92 Ok(())
93 }
94
95 pub fn background_executor(&self) -> &BackgroundExecutor {
96 &self.background_executor
97 }
98
99 pub fn foreground_executor(&self) -> &ForegroundExecutor {
100 &self.foreground_executor
101 }
102
103 pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
104 let app = self
105 .app
106 .upgrade()
107 .ok_or_else(|| anyhow!("app was released"))?;
108 let mut lock = app.borrow_mut();
109 Ok(f(&mut *lock))
110 }
111
112 pub fn open_window<V>(
113 &self,
114 options: crate::WindowOptions,
115 build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
116 ) -> Result<WindowHandle<V>>
117 where
118 V: 'static + Render,
119 {
120 let app = self
121 .app
122 .upgrade()
123 .ok_or_else(|| anyhow!("app was released"))?;
124 let mut lock = app.borrow_mut();
125 Ok(lock.open_window(options, build_root_view))
126 }
127
128 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
129 where
130 Fut: Future<Output = R> + 'static,
131 R: 'static,
132 {
133 self.foreground_executor.spawn(f(self.clone()))
134 }
135
136 pub fn has_global<G: 'static>(&self) -> Result<bool> {
137 let app = self
138 .app
139 .upgrade()
140 .ok_or_else(|| anyhow!("app was released"))?;
141 let app = app.borrow_mut();
142 Ok(app.has_global::<G>())
143 }
144
145 pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
146 let app = self
147 .app
148 .upgrade()
149 .ok_or_else(|| anyhow!("app was released"))?;
150 let app = app.borrow_mut();
151 Ok(read(app.global(), &app))
152 }
153
154 pub fn try_read_global<G: 'static, R>(
155 &self,
156 read: impl FnOnce(&G, &AppContext) -> R,
157 ) -> Option<R> {
158 let app = self.app.upgrade()?;
159 let app = app.borrow_mut();
160 Some(read(app.try_global()?, &app))
161 }
162
163 pub fn update_global<G: 'static, R>(
164 &mut self,
165 update: impl FnOnce(&mut G, &mut AppContext) -> R,
166 ) -> Result<R> {
167 let app = self
168 .app
169 .upgrade()
170 .ok_or_else(|| anyhow!("app was released"))?;
171 let mut app = app.borrow_mut();
172 Ok(app.update_global(update))
173 }
174}
175
176#[derive(Clone, Deref, DerefMut)]
177pub struct AsyncWindowContext {
178 #[deref]
179 #[deref_mut]
180 app: AsyncAppContext,
181 window: AnyWindowHandle,
182}
183
184impl AsyncWindowContext {
185 pub fn window_handle(&self) -> AnyWindowHandle {
186 self.window
187 }
188
189 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
190 Self { app, window }
191 }
192
193 pub fn update<R>(
194 &mut self,
195 update: impl FnOnce(AnyView, &mut WindowContext) -> R,
196 ) -> Result<R> {
197 self.app.update_window(self.window, update)
198 }
199
200 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
201 self.window.update(self, |_, cx| cx.on_next_frame(f)).ok();
202 }
203
204 pub fn read_global<G: 'static, R>(
205 &mut self,
206 read: impl FnOnce(&G, &WindowContext) -> R,
207 ) -> Result<R> {
208 self.window.update(self, |_, cx| read(cx.global(), cx))
209 }
210
211 pub fn update_global<G, R>(
212 &mut self,
213 update: impl FnOnce(&mut G, &mut WindowContext) -> R,
214 ) -> Result<R>
215 where
216 G: 'static,
217 {
218 self.window.update(self, |_, cx| cx.update_global(update))
219 }
220
221 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncWindowContext) -> Fut) -> Task<R>
222 where
223 Fut: Future<Output = R> + 'static,
224 R: 'static,
225 {
226 self.foreground_executor.spawn(f(self.clone()))
227 }
228}
229
230impl Context for AsyncWindowContext {
231 type Result<T> = Result<T>;
232
233 fn build_model<T>(
234 &mut self,
235 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
236 ) -> Result<Model<T>>
237 where
238 T: 'static,
239 {
240 self.window
241 .update(self, |_, cx| cx.build_model(build_model))
242 }
243
244 fn update_model<T: 'static, R>(
245 &mut self,
246 handle: &Model<T>,
247 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
248 ) -> Result<R> {
249 self.window
250 .update(self, |_, cx| cx.update_model(handle, update))
251 }
252
253 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
254 where
255 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
256 {
257 self.app.update_window(window, update)
258 }
259
260 fn read_model<T, R>(
261 &self,
262 handle: &Model<T>,
263 read: impl FnOnce(&T, &AppContext) -> R,
264 ) -> Self::Result<R>
265 where
266 T: 'static,
267 {
268 self.app.read_model(handle, read)
269 }
270
271 fn read_window<T, R>(
272 &self,
273 window: &WindowHandle<T>,
274 read: impl FnOnce(View<T>, &AppContext) -> R,
275 ) -> Result<R>
276 where
277 T: 'static,
278 {
279 self.app.read_window(window, read)
280 }
281}
282
283impl VisualContext for AsyncWindowContext {
284 fn build_view<V>(
285 &mut self,
286 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
287 ) -> Self::Result<View<V>>
288 where
289 V: 'static + Render,
290 {
291 self.window
292 .update(self, |_, cx| cx.build_view(build_view_state))
293 }
294
295 fn update_view<V: 'static, R>(
296 &mut self,
297 view: &View<V>,
298 update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
299 ) -> Self::Result<R> {
300 self.window
301 .update(self, |_, cx| cx.update_view(view, update))
302 }
303
304 fn replace_root_view<V>(
305 &mut self,
306 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
307 ) -> Self::Result<View<V>>
308 where
309 V: 'static + Render,
310 {
311 self.window
312 .update(self, |_, cx| cx.replace_root_view(build_view))
313 }
314
315 fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
316 where
317 V: FocusableView,
318 {
319 self.window.update(self, |_, cx| {
320 view.read(cx).focus_handle(cx).clone().focus(cx);
321 })
322 }
323
324 fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
325 where
326 V: crate::ManagedView,
327 {
328 self.window.update(self, |_, cx| {
329 view.update(cx, |_, cx| cx.emit(DismissEvent::Dismiss))
330 })
331 }
332}