model_context.rs

  1use crate::{
  2    AppContext, Context, Effect, EntityId, EventEmitter, Handle, Reference, Subscription,
  3    WeakHandle,
  4};
  5use std::marker::PhantomData;
  6
  7pub struct ModelContext<'a, T> {
  8    app: Reference<'a, AppContext>,
  9    entity_type: PhantomData<T>,
 10    entity_id: EntityId,
 11}
 12
 13impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
 14    pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self {
 15        Self {
 16            app: Reference::Mutable(app),
 17            entity_type: PhantomData,
 18            entity_id,
 19        }
 20    }
 21
 22    // todo!
 23    // fn update<R>(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R {
 24    //     let mut entity = self
 25    //         .app
 26    //         .entities
 27    //         .get_mut(self.entity_id)
 28    //         .unwrap()
 29    //         .take()
 30    //         .unwrap();
 31    //     let result = update(entity.downcast_mut::<T>().unwrap(), self);
 32    //     self.app
 33    //         .entities
 34    //         .get_mut(self.entity_id)
 35    //         .unwrap()
 36    //         .replace(entity);
 37    //     result
 38    // }
 39
 40    pub fn handle(&self) -> WeakHandle<T> {
 41        self.app.entities.weak_handle(self.entity_id)
 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    ) -> Subscription {
 49        let this = self.handle();
 50        let handle = handle.downgrade();
 51        self.app.observers.insert(
 52            handle.id,
 53            Box::new(move |cx| {
 54                if let Some((this, handle)) = this.upgrade(cx).zip(handle.upgrade(cx)) {
 55                    this.update(cx, |this, cx| on_notify(this, handle, cx));
 56                    true
 57                } else {
 58                    false
 59                }
 60            }),
 61        )
 62    }
 63
 64    pub fn subscribe<E: EventEmitter + Send + Sync + 'static>(
 65        &mut self,
 66        handle: &Handle<E>,
 67        on_event: impl Fn(&mut T, Handle<E>, &E::Event, &mut ModelContext<'_, T>)
 68            + Send
 69            + Sync
 70            + 'static,
 71    ) -> Subscription {
 72        let this = self.handle();
 73        let handle = handle.downgrade();
 74        self.app.event_handlers.insert(
 75            handle.id,
 76            Box::new(move |event, cx| {
 77                let event = event.downcast_ref().expect("invalid event type");
 78                if let Some((this, handle)) = this.upgrade(cx).zip(handle.upgrade(cx)) {
 79                    this.update(cx, |this, cx| on_event(this, handle, event, cx));
 80                    true
 81                } else {
 82                    false
 83                }
 84            }),
 85        )
 86    }
 87
 88    pub fn on_release(
 89        &mut self,
 90        on_release: impl Fn(&mut T, &mut AppContext) + Send + Sync + 'static,
 91    ) -> Subscription {
 92        self.app.release_handlers.insert(
 93            self.entity_id,
 94            Box::new(move |this, cx| {
 95                let this = this.downcast_mut().expect("invalid entity type");
 96                on_release(this, cx);
 97            }),
 98        )
 99    }
100
101    pub fn observe_release<E: Send + Sync + 'static>(
102        &mut self,
103        handle: &Handle<E>,
104        on_release: impl Fn(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + Sync + 'static,
105    ) -> Subscription {
106        let this = self.handle();
107        self.app.release_handlers.insert(
108            handle.id,
109            Box::new(move |entity, cx| {
110                let entity = entity.downcast_mut().expect("invalid entity type");
111                if let Some(this) = this.upgrade(cx) {
112                    this.update(cx, |this, cx| on_release(this, entity, cx));
113                }
114            }),
115        )
116    }
117
118    pub fn notify(&mut self) {
119        self.app.push_effect(Effect::Notify {
120            emitter: self.entity_id,
121        });
122    }
123}
124
125impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
126    pub fn emit(&mut self, event: T::Event) {
127        self.app.push_effect(Effect::Emit {
128            emitter: self.entity_id,
129            event: Box::new(event),
130        });
131    }
132}
133
134impl<'a, T: 'static> Context for ModelContext<'a, T> {
135    type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>;
136    type Result<U> = U;
137
138    fn entity<U: Send + Sync + 'static>(
139        &mut self,
140        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U,
141    ) -> Handle<U> {
142        self.app.entity(build_entity)
143    }
144
145    fn update_entity<U: Send + Sync + 'static, R>(
146        &mut self,
147        handle: &Handle<U>,
148        update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
149    ) -> R {
150        self.app.update_entity(handle, update)
151    }
152}