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