1use crate::{
2 AnyWindowHandle, AppContext, BackgroundExecutor, Context, ForegroundExecutor, Model,
3 ModelContext, Result, Task, WindowContext,
4};
5use anyhow::anyhow;
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 ModelContext<'a, T> = ModelContext<'a, T>;
18 type Result<T> = Result<T>;
19
20 fn build_model<T: 'static>(
21 &mut self,
22 build_model: impl FnOnce(&mut Self::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 Self::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
49impl AsyncAppContext {
50 pub fn refresh(&mut self) -> Result<()> {
51 let app = self
52 .app
53 .upgrade()
54 .ok_or_else(|| anyhow!("app was released"))?;
55 let mut lock = app.borrow_mut();
56 lock.refresh();
57 Ok(())
58 }
59
60 pub fn background_executor(&self) -> &BackgroundExecutor {
61 &self.background_executor
62 }
63
64 pub fn foreground_executor(&self) -> &ForegroundExecutor {
65 &self.foreground_executor
66 }
67
68 pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
69 let app = self
70 .app
71 .upgrade()
72 .ok_or_else(|| anyhow!("app was released"))?;
73 let mut lock = app.borrow_mut();
74 Ok(f(&mut *lock))
75 }
76
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 .app
84 .upgrade()
85 .ok_or_else(|| anyhow!("app was released"))?;
86 let app_context = app.borrow();
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 .app
97 .upgrade()
98 .ok_or_else(|| anyhow!("app was released"))?;
99 let mut app_context = app.borrow_mut();
100 app_context.update_window(handle.id, update)
101 }
102
103 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
104 where
105 Fut: Future<Output = R> + 'static,
106 R: 'static,
107 {
108 self.foreground_executor.spawn(f(self.clone()))
109 }
110
111 pub fn has_global<G: 'static>(&self) -> Result<bool> {
112 let app = self
113 .app
114 .upgrade()
115 .ok_or_else(|| anyhow!("app was released"))?;
116 let app = app.borrow_mut();
117 Ok(app.has_global::<G>())
118 }
119
120 pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
121 let app = self
122 .app
123 .upgrade()
124 .ok_or_else(|| anyhow!("app was released"))?;
125 let app = app.borrow_mut(); // Need this to compile
126 Ok(read(app.global(), &app))
127 }
128
129 pub fn try_read_global<G: 'static, R>(
130 &self,
131 read: impl FnOnce(&G, &AppContext) -> R,
132 ) -> Option<R> {
133 let app = self.app.upgrade()?;
134 let app = app.borrow_mut();
135 Some(read(app.try_global()?, &app))
136 }
137
138 pub fn update_global<G: 'static, R>(
139 &mut self,
140 update: impl FnOnce(&mut G, &mut AppContext) -> R,
141 ) -> Result<R> {
142 let app = self
143 .app
144 .upgrade()
145 .ok_or_else(|| anyhow!("app was released"))?;
146 let mut app = app.borrow_mut();
147 Ok(app.update_global(update))
148 }
149}
150
151#[derive(Clone, Deref, DerefMut)]
152pub struct AsyncWindowContext {
153 #[deref]
154 #[deref_mut]
155 app: AsyncAppContext,
156 window: AnyWindowHandle,
157}
158
159impl AsyncWindowContext {
160 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
161 Self { app, window }
162 }
163
164 pub fn update<R>(&self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
165 self.app.update_window(self.window, update)
166 }
167
168 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
169 self.app
170 .update_window(self.window, |cx| cx.on_next_frame(f))
171 .ok();
172 }
173
174 pub fn read_global<G: 'static, R>(
175 &self,
176 read: impl FnOnce(&G, &WindowContext) -> R,
177 ) -> Result<R> {
178 self.app
179 .read_window(self.window, |cx| read(cx.global(), cx))
180 }
181
182 pub fn update_global<G, R>(
183 &mut self,
184 update: impl FnOnce(&mut G, &mut WindowContext) -> R,
185 ) -> Result<R>
186 where
187 G: 'static,
188 {
189 self.app
190 .update_window(self.window, |cx| cx.update_global(update))
191 }
192}
193
194impl Context for AsyncWindowContext {
195 type ModelContext<'a, T> = ModelContext<'a, T>;
196 type Result<T> = Result<T>;
197
198 fn build_model<T>(
199 &mut self,
200 build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
201 ) -> Result<Model<T>>
202 where
203 T: 'static,
204 {
205 self.app
206 .update_window(self.window, |cx| cx.build_model(build_model))
207 }
208
209 fn update_model<T: 'static, R>(
210 &mut self,
211 handle: &Model<T>,
212 update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
213 ) -> Result<R> {
214 self.app
215 .update_window(self.window, |cx| cx.update_model(handle, update))
216 }
217}