async_context.rs

  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}