async_context.rs

  1use crate::{
  2    AnyWindowHandle, AppContext, Context, Handle, ModelContext, Result, ViewContext, WindowContext,
  3};
  4use anyhow::anyhow;
  5use parking_lot::Mutex;
  6use std::sync::Weak;
  7
  8#[derive(Clone)]
  9pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
 10
 11impl Context for AsyncAppContext {
 12    type BorrowedContext<'a, 'w> = AppContext;
 13    type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
 14    type Result<T> = Result<T>;
 15
 16    fn entity<T: Send + Sync + 'static>(
 17        &mut self,
 18        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
 19    ) -> Self::Result<Handle<T>> {
 20        let app = self
 21            .0
 22            .upgrade()
 23            .ok_or_else(|| anyhow!("app was released"))?;
 24        let mut lock = app.lock();
 25        Ok(lock.entity(build_entity))
 26    }
 27
 28    fn update_entity<T: Send + Sync + 'static, R>(
 29        &mut self,
 30        handle: &Handle<T>,
 31        update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
 32    ) -> Self::Result<R> {
 33        let app = self
 34            .0
 35            .upgrade()
 36            .ok_or_else(|| anyhow!("app was released"))?;
 37        let mut lock = app.lock();
 38        Ok(lock.update_entity(handle, update))
 39    }
 40
 41    fn read_global<G: 'static + Send + Sync, R>(
 42        &self,
 43        read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
 44    ) -> Self::Result<R> {
 45        let app = self
 46            .0
 47            .upgrade()
 48            .ok_or_else(|| anyhow!("app was released"))?;
 49        let mut lock = app.lock();
 50        Ok(lock.read_global(read))
 51    }
 52}
 53
 54impl AsyncAppContext {
 55    pub fn read_window<R>(
 56        &self,
 57        handle: AnyWindowHandle,
 58        update: impl FnOnce(&WindowContext) -> R,
 59    ) -> Result<R> {
 60        let app = self
 61            .0
 62            .upgrade()
 63            .ok_or_else(|| anyhow!("app was released"))?;
 64        let mut app_context = app.lock();
 65        app_context.read_window(handle.id, update)
 66    }
 67
 68    pub fn update_window<R>(
 69        &self,
 70        handle: AnyWindowHandle,
 71        update: impl FnOnce(&mut WindowContext) -> R,
 72    ) -> Result<R> {
 73        let app = self
 74            .0
 75            .upgrade()
 76            .ok_or_else(|| anyhow!("app was released"))?;
 77        let mut app_context = app.lock();
 78        app_context.update_window(handle.id, update)
 79    }
 80}
 81
 82#[derive(Clone)]
 83pub struct AsyncWindowContext {
 84    app: AsyncAppContext,
 85    window: AnyWindowHandle,
 86}
 87
 88impl AsyncWindowContext {
 89    pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
 90        Self { app, window }
 91    }
 92
 93    pub fn update<R>(&self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
 94        self.app.update_window(self.window, update)
 95    }
 96
 97    pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
 98        self.app
 99            .update_window(self.window, |cx| cx.on_next_frame(f))
100            .ok();
101    }
102}
103
104impl Context for AsyncWindowContext {
105    type BorrowedContext<'a, 'w> = WindowContext<'a, 'w>;
106    type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
107    type Result<T> = Result<T>;
108
109    fn entity<R: Send + Sync + 'static>(
110        &mut self,
111        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
112    ) -> Result<Handle<R>> {
113        self.app
114            .update_window(self.window, |cx| cx.entity(build_entity))
115    }
116
117    fn update_entity<T: Send + Sync + 'static, R>(
118        &mut self,
119        handle: &Handle<T>,
120        update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
121    ) -> Result<R> {
122        self.app
123            .update_window(self.window, |cx| cx.update_entity(handle, update))
124    }
125
126    fn read_global<G: 'static + Send + Sync, R>(
127        &self,
128        read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
129    ) -> Result<R> {
130        self.app.read_window(self.window, |cx| cx.read_global(read))
131    }
132}