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