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