1use crate::{
2 AppContext, AsyncAppContext, Context, Effect, Entity, EntityId, EventEmitter, MainThread,
3 Model, Subscription, Task, WeakModel,
4};
5use derive_more::{Deref, DerefMut};
6use futures::FutureExt;
7use std::{
8 any::{Any, TypeId},
9 borrow::{Borrow, BorrowMut},
10 future::Future,
11};
12
13#[derive(Deref, DerefMut)]
14pub struct ModelContext<'a, T> {
15 #[deref]
16 #[deref_mut]
17 app: &'a mut AppContext,
18 model_state: WeakModel<T>,
19}
20
21impl<'a, T: 'static> ModelContext<'a, T> {
22 pub(crate) fn new(app: &'a mut AppContext, model_state: WeakModel<T>) -> Self {
23 Self { app, model_state }
24 }
25
26 pub fn entity_id(&self) -> EntityId {
27 self.model_state.entity_id
28 }
29
30 pub fn handle(&self) -> Model<T> {
31 self.weak_model()
32 .upgrade()
33 .expect("The entity must be alive if we have a model context")
34 }
35
36 pub fn weak_model(&self) -> WeakModel<T> {
37 self.model_state.clone()
38 }
39
40 pub fn observe<T2, E>(
41 &mut self,
42 entity: &E,
43 mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, T>) + Send + 'static,
44 ) -> Subscription
45 where
46 T: 'static + Send,
47 T2: 'static,
48 E: Entity<T2>,
49 {
50 let this = self.weak_model();
51 let entity_id = entity.entity_id();
52 let handle = entity.downgrade();
53 self.app.observers.insert(
54 entity_id,
55 Box::new(move |cx| {
56 if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&handle)) {
57 this.update(cx, |this, cx| on_notify(this, handle, cx));
58 true
59 } else {
60 false
61 }
62 }),
63 )
64 }
65
66 pub fn subscribe<T2, E>(
67 &mut self,
68 entity: &E,
69 mut on_event: impl FnMut(&mut T, E, &T2::Event, &mut ModelContext<'_, T>) + Send + 'static,
70 ) -> Subscription
71 where
72 T: 'static + Send,
73 T2: 'static + EventEmitter,
74 E: Entity<T2>,
75 {
76 let this = self.weak_model();
77 let entity_id = entity.entity_id();
78 let entity = entity.downgrade();
79 self.app.event_listeners.insert(
80 entity_id,
81 Box::new(move |event, cx| {
82 let event: &T2::Event = event.downcast_ref().expect("invalid event type");
83 if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&entity)) {
84 this.update(cx, |this, cx| on_event(this, handle, event, cx));
85 true
86 } else {
87 false
88 }
89 }),
90 )
91 }
92
93 pub fn on_release(
94 &mut self,
95 mut on_release: impl FnMut(&mut T, &mut AppContext) + Send + 'static,
96 ) -> Subscription
97 where
98 T: 'static,
99 {
100 self.app.release_listeners.insert(
101 self.model_state.entity_id,
102 Box::new(move |this, cx| {
103 let this = this.downcast_mut().expect("invalid entity type");
104 on_release(this, cx);
105 }),
106 )
107 }
108
109 pub fn observe_release<T2, E>(
110 &mut self,
111 entity: &E,
112 mut on_release: impl FnMut(&mut T, &mut T2, &mut ModelContext<'_, T>) + Send + 'static,
113 ) -> Subscription
114 where
115 T: Any + Send,
116 T2: 'static,
117 E: Entity<T2>,
118 {
119 let entity_id = entity.entity_id();
120 let this = self.weak_model();
121 self.app.release_listeners.insert(
122 entity_id,
123 Box::new(move |entity, cx| {
124 let entity = entity.downcast_mut().expect("invalid entity type");
125 if let Some(this) = this.upgrade() {
126 this.update(cx, |this, cx| on_release(this, entity, cx));
127 }
128 }),
129 )
130 }
131
132 pub fn observe_global<G: 'static>(
133 &mut self,
134 mut f: impl FnMut(&mut T, &mut ModelContext<'_, T>) + Send + 'static,
135 ) -> Subscription
136 where
137 T: 'static + Send,
138 {
139 let handle = self.weak_model();
140 self.global_observers.insert(
141 TypeId::of::<G>(),
142 Box::new(move |cx| handle.update(cx, |view, cx| f(view, cx)).is_ok()),
143 )
144 }
145
146 pub fn on_app_quit<Fut>(
147 &mut self,
148 mut on_quit: impl FnMut(&mut T, &mut ModelContext<T>) -> Fut + Send + 'static,
149 ) -> Subscription
150 where
151 Fut: 'static + Future<Output = ()> + Send,
152 T: 'static + Send,
153 {
154 let handle = self.weak_model();
155 self.app.quit_observers.insert(
156 (),
157 Box::new(move |cx| {
158 let future = handle.update(cx, |entity, cx| on_quit(entity, cx)).ok();
159 async move {
160 if let Some(future) = future {
161 future.await;
162 }
163 }
164 .boxed()
165 }),
166 )
167 }
168
169 pub fn notify(&mut self) {
170 if self
171 .app
172 .pending_notifications
173 .insert(self.model_state.entity_id)
174 {
175 self.app.pending_effects.push_back(Effect::Notify {
176 emitter: self.model_state.entity_id,
177 });
178 }
179 }
180
181 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
182 where
183 G: 'static + Send,
184 {
185 let mut global = self.app.lease_global::<G>();
186 let result = f(&mut global, self);
187 self.app.end_global_lease(global);
188 result
189 }
190
191 pub fn spawn<Fut, R>(
192 &self,
193 f: impl FnOnce(WeakModel<T>, AsyncAppContext) -> Fut + Send + 'static,
194 ) -> Task<R>
195 where
196 T: 'static,
197 Fut: Future<Output = R> + Send + 'static,
198 R: Send + 'static,
199 {
200 let this = self.weak_model();
201 self.app.spawn(|cx| f(this, cx))
202 }
203
204 pub fn spawn_on_main<Fut, R>(
205 &self,
206 f: impl FnOnce(WeakModel<T>, MainThread<AsyncAppContext>) -> Fut + Send + 'static,
207 ) -> Task<R>
208 where
209 Fut: Future<Output = R> + 'static,
210 R: Send + 'static,
211 {
212 let this = self.weak_model();
213 self.app.spawn_on_main(|cx| f(this, cx))
214 }
215}
216
217impl<'a, T> ModelContext<'a, T>
218where
219 T: EventEmitter,
220 T::Event: Send,
221{
222 pub fn emit(&mut self, event: T::Event) {
223 self.app.pending_effects.push_back(Effect::Emit {
224 emitter: self.model_state.entity_id,
225 event: Box::new(event),
226 });
227 }
228}
229
230impl<'a, T> Context for ModelContext<'a, T> {
231 type ModelContext<'b, U> = ModelContext<'b, U>;
232 type Result<U> = U;
233
234 fn build_model<U>(
235 &mut self,
236 build_model: impl FnOnce(&mut Self::ModelContext<'_, U>) -> U,
237 ) -> Model<U>
238 where
239 U: 'static + Send,
240 {
241 self.app.build_model(build_model)
242 }
243
244 fn update_model<U: 'static, R>(
245 &mut self,
246 handle: &Model<U>,
247 update: impl FnOnce(&mut U, &mut Self::ModelContext<'_, U>) -> R,
248 ) -> R {
249 self.app.update_model(handle, update)
250 }
251}
252
253impl<T> Borrow<AppContext> for ModelContext<'_, T> {
254 fn borrow(&self) -> &AppContext {
255 &self.app
256 }
257}
258
259impl<T> BorrowMut<AppContext> for ModelContext<'_, T> {
260 fn borrow_mut(&mut self) -> &mut AppContext {
261 &mut self.app
262 }
263}