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 refresh(&mut self) -> Self::Result<()> {
17 let app = self
18 .0
19 .upgrade()
20 .ok_or_else(|| anyhow!("app was released"))?;
21 let mut lock = app.lock(); // Need this to compile
22 lock.refresh();
23 Ok(())
24 }
25
26 fn entity<T: Send + Sync + 'static>(
27 &mut self,
28 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
29 ) -> Self::Result<Handle<T>> {
30 let app = self
31 .0
32 .upgrade()
33 .ok_or_else(|| anyhow!("app was released"))?;
34 let mut lock = app.lock(); // Need this to compile
35 Ok(lock.entity(build_entity))
36 }
37
38 fn update_entity<T: Send + Sync + 'static, R>(
39 &mut self,
40 handle: &Handle<T>,
41 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
42 ) -> Self::Result<R> {
43 let app = self
44 .0
45 .upgrade()
46 .ok_or_else(|| anyhow!("app was released"))?;
47 let mut lock = app.lock(); // Need this to compile
48 Ok(lock.update_entity(handle, update))
49 }
50
51 fn read_global<G: 'static + Send + Sync, R>(
52 &self,
53 read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
54 ) -> Self::Result<R> {
55 let app = self
56 .0
57 .upgrade()
58 .ok_or_else(|| anyhow!("app was released"))?;
59 let lock = app.lock(); // Need this to compile
60 Ok(lock.read_global(read))
61 }
62
63 fn update_global<G: 'static + Send + Sync, R>(
64 &mut self,
65 update: impl FnOnce(&mut G, &mut Self::BorrowedContext<'_, '_>) -> R,
66 ) -> Self::Result<R> {
67 let app = self
68 .0
69 .upgrade()
70 .ok_or_else(|| anyhow!("app was released"))?;
71 let mut lock = app.lock(); // Need this to compile
72 Ok(lock.update_global(update))
73 }
74}
75
76impl AsyncAppContext {
77 pub fn read_window<R>(
78 &self,
79 handle: AnyWindowHandle,
80 update: impl FnOnce(&WindowContext) -> R,
81 ) -> Result<R> {
82 let app = self
83 .0
84 .upgrade()
85 .ok_or_else(|| anyhow!("app was released"))?;
86 let mut app_context = app.lock();
87 app_context.read_window(handle.id, update)
88 }
89
90 pub fn update_window<R>(
91 &self,
92 handle: AnyWindowHandle,
93 update: impl FnOnce(&mut WindowContext) -> R,
94 ) -> Result<R> {
95 let app = self
96 .0
97 .upgrade()
98 .ok_or_else(|| anyhow!("app was released"))?;
99 let mut app_context = app.lock();
100 app_context.update_window(handle.id, update)
101 }
102}
103
104#[derive(Clone)]
105pub struct AsyncWindowContext {
106 app: AsyncAppContext,
107 window: AnyWindowHandle,
108}
109
110impl AsyncWindowContext {
111 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
112 Self { app, window }
113 }
114
115 pub fn update<R>(&self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
116 self.app.update_window(self.window, update)
117 }
118
119 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
120 self.app
121 .update_window(self.window, |cx| cx.on_next_frame(f))
122 .ok();
123 }
124}
125
126impl Context for AsyncWindowContext {
127 type BorrowedContext<'a, 'w> = WindowContext<'a, 'w>;
128 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
129 type Result<T> = Result<T>;
130
131 fn refresh(&mut self) -> Self::Result<()> {
132 self.app.refresh()
133 }
134
135 fn entity<R: Send + Sync + 'static>(
136 &mut self,
137 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
138 ) -> Result<Handle<R>> {
139 self.app
140 .update_window(self.window, |cx| cx.entity(build_entity))
141 }
142
143 fn update_entity<T: Send + Sync + 'static, R>(
144 &mut self,
145 handle: &Handle<T>,
146 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
147 ) -> Result<R> {
148 self.app
149 .update_window(self.window, |cx| cx.update_entity(handle, update))
150 }
151
152 fn read_global<G: 'static + Send + Sync, R>(
153 &self,
154 read: impl FnOnce(&G, &Self::BorrowedContext<'_, '_>) -> R,
155 ) -> Result<R> {
156 self.app.read_window(self.window, |cx| cx.read_global(read))
157 }
158
159 fn update_global<G: 'static + Send + Sync, R>(
160 &mut self,
161 update: impl FnOnce(&mut G, &mut Self::BorrowedContext<'_, '_>) -> R,
162 ) -> Result<R> {
163 self.app
164 .update_window(self.window, |cx| cx.update_global(update))
165 }
166}