model_context.rs

 1use crate::{AppContext, Context, Effect, EntityId, Handle, Reference, WeakHandle};
 2use std::{marker::PhantomData, sync::Arc};
 3
 4pub struct ModelContext<'a, T> {
 5    app: Reference<'a, AppContext>,
 6    entity_type: PhantomData<T>,
 7    entity_id: EntityId,
 8}
 9
10impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
11    pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self {
12        Self {
13            app: Reference::Mutable(app),
14            entity_type: PhantomData,
15            entity_id,
16        }
17    }
18
19    // todo!
20    // fn update<R>(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R {
21    //     let mut entity = self
22    //         .app
23    //         .entities
24    //         .get_mut(self.entity_id)
25    //         .unwrap()
26    //         .take()
27    //         .unwrap();
28    //     let result = update(entity.downcast_mut::<T>().unwrap(), self);
29    //     self.app
30    //         .entities
31    //         .get_mut(self.entity_id)
32    //         .unwrap()
33    //         .replace(entity);
34    //     result
35    // }
36
37    pub fn handle(&self) -> WeakHandle<T> {
38        WeakHandle {
39            id: self.entity_id,
40            entity_type: PhantomData,
41        }
42    }
43
44    pub fn observe<E: Send + Sync + 'static>(
45        &mut self,
46        handle: &Handle<E>,
47        on_notify: impl Fn(&mut T, Handle<E>, &mut ModelContext<'_, T>) + Send + Sync + 'static,
48    ) {
49        let this = self.handle();
50        let handle = handle.downgrade();
51        self.app
52            .observers
53            .entry(handle.id)
54            .or_default()
55            .push(Arc::new(move |cx| {
56                if let Some((this, handle)) = this.upgrade(cx).zip(handle.upgrade(cx)) {
57                    this.update(cx, |this, cx| on_notify(this, handle, cx));
58                    true
59                } else {
60                    false
61                }
62            }));
63    }
64
65    pub fn notify(&mut self) {
66        self.app
67            .pending_effects
68            .push_back(Effect::Notify(self.entity_id));
69    }
70}
71
72impl<'a, T: 'static> Context for ModelContext<'a, T> {
73    type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>;
74    type Result<U> = U;
75
76    fn entity<U: Send + Sync + 'static>(
77        &mut self,
78        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U,
79    ) -> Handle<U> {
80        self.app.entity(build_entity)
81    }
82
83    fn update_entity<U: Send + Sync + 'static, R>(
84        &mut self,
85        handle: &Handle<U>,
86        update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
87    ) -> R {
88        self.app.update_entity(handle, update)
89    }
90}