mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-06 02:37:21 +00:00
Add the entity trait and implement for models, views, subscriptions, and observations
This commit is contained in:
parent
58446c2715
commit
327a2f9967
13 changed files with 183 additions and 101 deletions
|
@ -67,8 +67,8 @@ impl ActiveCall {
|
|||
incoming_call: watch::channel(),
|
||||
|
||||
_subscriptions: vec![
|
||||
client.add_request_handler(cx.weak_handle(), Self::handle_incoming_call),
|
||||
client.add_message_handler(cx.weak_handle(), Self::handle_call_canceled),
|
||||
client.add_request_handler(cx.weak_model(), Self::handle_incoming_call),
|
||||
client.add_message_handler(cx.weak_model(), Self::handle_call_canceled),
|
||||
],
|
||||
client,
|
||||
user_store,
|
||||
|
|
|
@ -122,9 +122,9 @@ impl UserStore {
|
|||
let (mut current_user_tx, current_user_rx) = watch::channel();
|
||||
let (update_contacts_tx, mut update_contacts_rx) = mpsc::unbounded();
|
||||
let rpc_subscriptions = vec![
|
||||
client.add_message_handler(cx.weak_handle(), Self::handle_update_contacts),
|
||||
client.add_message_handler(cx.weak_handle(), Self::handle_update_invite_info),
|
||||
client.add_message_handler(cx.weak_handle(), Self::handle_show_contacts),
|
||||
client.add_message_handler(cx.weak_model(), Self::handle_update_contacts),
|
||||
client.add_message_handler(cx.weak_model(), Self::handle_update_invite_info),
|
||||
client.add_message_handler(cx.weak_model(), Self::handle_show_contacts),
|
||||
];
|
||||
Self {
|
||||
users: Default::default(),
|
||||
|
|
|
@ -7,8 +7,8 @@ use async_tar::Archive;
|
|||
use collections::{HashMap, HashSet};
|
||||
use futures::{channel::oneshot, future::Shared, Future, FutureExt, TryFutureExt};
|
||||
use gpui2::{
|
||||
AppContext, AsyncAppContext, Context, EntityId, EventEmitter, Model, ModelContext, Task,
|
||||
WeakModel,
|
||||
AppContext, AsyncAppContext, Context, Entity, EntityId, EventEmitter, Model, ModelContext,
|
||||
Task, WeakModel,
|
||||
};
|
||||
use language2::{
|
||||
language_settings::{all_language_settings, language_settings},
|
||||
|
|
|
@ -726,7 +726,7 @@ impl Context for AppContext {
|
|||
|
||||
/// Update the entity referenced by the given model. The function is passed a mutable reference to the
|
||||
/// entity along with a `ModelContext` for the entity.
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
model: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
|
|
|
@ -32,7 +32,7 @@ impl Context for AsyncAppContext {
|
|||
Ok(lock.build_model(build_model))
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
|
@ -42,7 +42,7 @@ impl Context for AsyncAppContext {
|
|||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.lock(); // Need this to compile
|
||||
Ok(lock.update_entity(handle, update))
|
||||
Ok(lock.update_model(handle, update))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,13 +230,13 @@ impl Context for AsyncWindowContext {
|
|||
.update_window(self.window, |cx| cx.build_model(build_model))
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
) -> Result<R> {
|
||||
self.app
|
||||
.update_window(self.window, |cx| cx.update_entity(handle, update))
|
||||
.update_window(self.window, |cx| cx.update_model(handle, update))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{AnyBox, AppContext, Context};
|
||||
use crate::{private::Sealed, AnyBox, AppContext, Context, Entity};
|
||||
use anyhow::{anyhow, Result};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||
|
@ -253,6 +253,32 @@ pub struct Model<T> {
|
|||
|
||||
unsafe impl<T> Send for Model<T> {}
|
||||
unsafe impl<T> Sync for Model<T> {}
|
||||
impl<T> Sealed for Model<T> {}
|
||||
|
||||
impl<T: 'static> Entity<T> for Model<T> {
|
||||
type Weak = WeakModel<T>;
|
||||
|
||||
fn entity_id(&self) -> EntityId {
|
||||
self.any_model.entity_id
|
||||
}
|
||||
|
||||
fn downgrade(&self) -> Self::Weak {
|
||||
WeakModel {
|
||||
any_model: self.any_model.downgrade(),
|
||||
entity_type: self.entity_type,
|
||||
}
|
||||
}
|
||||
|
||||
fn upgrade_from(weak: &Self::Weak) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Some(Model {
|
||||
any_model: weak.any_model.upgrade()?,
|
||||
entity_type: weak.entity_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> Model<T> {
|
||||
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
|
||||
|
@ -265,11 +291,12 @@ impl<T: 'static> Model<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Downgrade the this to a weak model reference
|
||||
pub fn downgrade(&self) -> WeakModel<T> {
|
||||
WeakModel {
|
||||
any_model: self.any_model.downgrade(),
|
||||
entity_type: self.entity_type,
|
||||
}
|
||||
// Delegate to the trait implementation to keep behavior in one place.
|
||||
// This method was included to improve method resolution in the presence of
|
||||
// the Model's deref
|
||||
Entity::downgrade(self)
|
||||
}
|
||||
|
||||
/// Convert this into a dynamically typed model.
|
||||
|
@ -294,7 +321,7 @@ impl<T: 'static> Model<T> {
|
|||
where
|
||||
C: Context,
|
||||
{
|
||||
cx.update_entity(self, update)
|
||||
cx.update_model(self, update)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +361,7 @@ impl<T> Eq for Model<T> {}
|
|||
|
||||
impl<T> PartialEq<WeakModel<T>> for Model<T> {
|
||||
fn eq(&self, other: &WeakModel<T>) -> bool {
|
||||
self.entity_id() == other.entity_id()
|
||||
self.any_model.entity_id() == other.entity_id()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,11 +442,10 @@ impl<T> Clone for WeakModel<T> {
|
|||
}
|
||||
|
||||
impl<T: 'static> WeakModel<T> {
|
||||
/// Upgrade this weak model reference into a strong model reference
|
||||
pub fn upgrade(&self) -> Option<Model<T>> {
|
||||
Some(Model {
|
||||
any_model: self.any_model.upgrade()?,
|
||||
entity_type: self.entity_type,
|
||||
})
|
||||
// Delegate to the trait implementation to keep behavior in one place.
|
||||
Model::upgrade_from(self)
|
||||
}
|
||||
|
||||
/// Update the entity referenced by this model with the given function if
|
||||
|
@ -441,7 +467,7 @@ impl<T: 'static> WeakModel<T> {
|
|||
crate::Flatten::flatten(
|
||||
self.upgrade()
|
||||
.ok_or_else(|| anyhow!("entity release"))
|
||||
.map(|this| cx.update_entity(&this, update)),
|
||||
.map(|this| cx.update_model(&this, update)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -462,6 +488,6 @@ impl<T> Eq for WeakModel<T> {}
|
|||
|
||||
impl<T> PartialEq<Model<T>> for WeakModel<T> {
|
||||
fn eq(&self, other: &Model<T>) -> bool {
|
||||
self.entity_id() == other.entity_id()
|
||||
self.entity_id() == other.any_model.entity_id()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, MainThread, Model,
|
||||
Reference, Subscription, Task, WeakModel,
|
||||
AppContext, AsyncAppContext, Context, Effect, Entity, EntityId, EventEmitter, MainThread,
|
||||
Model, Reference, Subscription, Task, WeakModel,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use futures::FutureExt;
|
||||
|
@ -31,29 +31,32 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
}
|
||||
|
||||
pub fn handle(&self) -> Model<T> {
|
||||
self.weak_handle()
|
||||
self.weak_model()
|
||||
.upgrade()
|
||||
.expect("The entity must be alive if we have a model context")
|
||||
}
|
||||
|
||||
pub fn weak_handle(&self) -> WeakModel<T> {
|
||||
pub fn weak_model(&self) -> WeakModel<T> {
|
||||
self.model_state.clone()
|
||||
}
|
||||
|
||||
pub fn observe<T2: 'static>(
|
||||
pub fn observe<T2, E>(
|
||||
&mut self,
|
||||
handle: &Model<T2>,
|
||||
mut on_notify: impl FnMut(&mut T, Model<T2>, &mut ModelContext<'_, T>) + Send + 'static,
|
||||
entity: &E,
|
||||
mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, T>) + Send + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static + Send,
|
||||
T2: 'static,
|
||||
E: Entity<T2>,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let handle = handle.downgrade();
|
||||
let this = self.weak_model();
|
||||
let entity_id = entity.entity_id();
|
||||
let handle = entity.downgrade();
|
||||
self.app.observers.insert(
|
||||
handle.entity_id,
|
||||
entity_id,
|
||||
Box::new(move |cx| {
|
||||
if let Some((this, handle)) = this.upgrade().zip(handle.upgrade()) {
|
||||
if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&handle)) {
|
||||
this.update(cx, |this, cx| on_notify(this, handle, cx));
|
||||
true
|
||||
} else {
|
||||
|
@ -63,21 +66,24 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<E: 'static + EventEmitter>(
|
||||
pub fn subscribe<T2, E>(
|
||||
&mut self,
|
||||
handle: &Model<E>,
|
||||
mut on_event: impl FnMut(&mut T, Model<E>, &E::Event, &mut ModelContext<'_, T>) + Send + 'static,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(&mut T, E, &T2::Event, &mut ModelContext<'_, T>) + Send + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static + Send,
|
||||
T2: 'static + EventEmitter,
|
||||
E: Entity<T2>,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let handle = handle.downgrade();
|
||||
let this = self.weak_model();
|
||||
let entity_id = entity.entity_id();
|
||||
let entity = entity.downgrade();
|
||||
self.app.event_listeners.insert(
|
||||
handle.entity_id,
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
let event: &E::Event = event.downcast_ref().expect("invalid event type");
|
||||
if let Some((this, handle)) = this.upgrade().zip(handle.upgrade()) {
|
||||
let event: &T2::Event = event.downcast_ref().expect("invalid event type");
|
||||
if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&entity)) {
|
||||
this.update(cx, |this, cx| on_event(this, handle, event, cx));
|
||||
true
|
||||
} else {
|
||||
|
@ -103,17 +109,20 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn observe_release<E: 'static>(
|
||||
pub fn observe_release<T2, E>(
|
||||
&mut self,
|
||||
handle: &Model<E>,
|
||||
mut on_release: impl FnMut(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + 'static,
|
||||
entity: &E,
|
||||
mut on_release: impl FnMut(&mut T, &mut T2, &mut ModelContext<'_, T>) + Send + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: Any + Send,
|
||||
T2: 'static,
|
||||
E: Entity<T2>,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let entity_id = entity.entity_id();
|
||||
let this = self.weak_model();
|
||||
self.app.release_listeners.insert(
|
||||
handle.entity_id,
|
||||
entity_id,
|
||||
Box::new(move |entity, cx| {
|
||||
let entity = entity.downcast_mut().expect("invalid entity type");
|
||||
if let Some(this) = this.upgrade() {
|
||||
|
@ -130,7 +139,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
where
|
||||
T: 'static + Send,
|
||||
{
|
||||
let handle = self.weak_handle();
|
||||
let handle = self.weak_model();
|
||||
self.global_observers.insert(
|
||||
TypeId::of::<G>(),
|
||||
Box::new(move |cx| handle.update(cx, |view, cx| f(view, cx)).is_ok()),
|
||||
|
@ -145,7 +154,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
Fut: 'static + Future<Output = ()> + Send,
|
||||
T: 'static + Send,
|
||||
{
|
||||
let handle = self.weak_handle();
|
||||
let handle = self.weak_model();
|
||||
self.app.quit_observers.insert(
|
||||
(),
|
||||
Box::new(move |cx| {
|
||||
|
@ -191,7 +200,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
Fut: Future<Output = R> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let this = self.weak_model();
|
||||
self.app.spawn(|cx| f(this, cx))
|
||||
}
|
||||
|
||||
|
@ -203,7 +212,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
Fut: Future<Output = R> + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let this = self.weak_model();
|
||||
self.app.spawn_on_main(|cx| f(this, cx))
|
||||
}
|
||||
}
|
||||
|
@ -235,12 +244,12 @@ impl<'a, T> Context for ModelContext<'a, T> {
|
|||
self.app.build_model(build_model)
|
||||
}
|
||||
|
||||
fn update_entity<U: 'static, R>(
|
||||
fn update_model<U: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<U>,
|
||||
update: impl FnOnce(&mut U, &mut Self::ModelContext<'_, U>) -> R,
|
||||
) -> R {
|
||||
self.app.update_entity(handle, update)
|
||||
self.app.update_model(handle, update)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,13 +26,13 @@ impl Context for TestAppContext {
|
|||
lock.build_model(build_model)
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
let mut lock = self.app.lock();
|
||||
lock.update_entity(handle, update)
|
||||
lock.update_model(handle, update)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,12 @@ mod util;
|
|||
mod view;
|
||||
mod window;
|
||||
|
||||
mod private {
|
||||
/// A mechanism for restricting implementations of a trait to only those in GPUI.
|
||||
/// See: https://predr.ag/blog/definitive-guide-to-sealed-traits-in-rust/
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
pub use action::*;
|
||||
pub use anyhow::Result;
|
||||
pub use app::*;
|
||||
|
@ -39,6 +45,7 @@ pub use image_cache::*;
|
|||
pub use interactive::*;
|
||||
pub use keymap::*;
|
||||
pub use platform::*;
|
||||
use private::Sealed;
|
||||
pub use refineable::*;
|
||||
pub use scene::*;
|
||||
pub use serde;
|
||||
|
@ -80,7 +87,7 @@ pub trait Context {
|
|||
where
|
||||
T: 'static + Send;
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
|
@ -104,6 +111,16 @@ pub trait VisualContext: Context {
|
|||
) -> Self::Result<R>;
|
||||
}
|
||||
|
||||
pub trait Entity<T>: Sealed {
|
||||
type Weak: 'static + Send;
|
||||
|
||||
fn entity_id(&self) -> EntityId;
|
||||
fn downgrade(&self) -> Self::Weak;
|
||||
fn upgrade_from(weak: &Self::Weak) -> Option<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub enum GlobalKey {
|
||||
Numeric(usize),
|
||||
View(EntityId),
|
||||
|
@ -149,12 +166,12 @@ impl<C: Context> Context for MainThread<C> {
|
|||
})
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
self.0.update_entity(handle, |entity, cx| {
|
||||
self.0.update_model(handle, |entity, cx| {
|
||||
let cx = unsafe {
|
||||
mem::transmute::<
|
||||
&mut C::ModelContext<'_, T>,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
AnyBox, AnyElement, AnyModel, AppContext, AvailableSpace, BorrowWindow, Bounds, Component,
|
||||
Element, ElementId, EntityId, LayoutId, Model, Pixels, Size, ViewContext, VisualContext,
|
||||
WeakModel, WindowContext,
|
||||
private::Sealed, AnyBox, AnyElement, AnyModel, AppContext, AvailableSpace, BorrowWindow,
|
||||
Bounds, Component, Element, ElementId, Entity, EntityId, LayoutId, Model, Pixels, Size,
|
||||
ViewContext, VisualContext, WeakModel, WindowContext,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use std::{any::TypeId, marker::PhantomData, sync::Arc};
|
||||
|
@ -16,19 +16,42 @@ pub struct View<V> {
|
|||
pub(crate) model: Model<V>,
|
||||
}
|
||||
|
||||
impl<V> Sealed for View<V> {}
|
||||
|
||||
impl<V: Render> View<V> {
|
||||
pub fn into_any(self) -> AnyView {
|
||||
AnyView(Arc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> View<V> {
|
||||
pub fn downgrade(&self) -> WeakView<V> {
|
||||
impl<V: 'static> Entity<V> for View<V> {
|
||||
type Weak = WeakView<V>;
|
||||
|
||||
fn entity_id(&self) -> EntityId {
|
||||
self.model.entity_id
|
||||
}
|
||||
|
||||
fn downgrade(&self) -> Self::Weak {
|
||||
WeakView {
|
||||
model: self.model.downgrade(),
|
||||
}
|
||||
}
|
||||
|
||||
fn upgrade_from(weak: &Self::Weak) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let model = weak.model.upgrade()?;
|
||||
Some(View { model })
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> View<V> {
|
||||
/// Convert this strong view reference into a weak view reference.
|
||||
pub fn downgrade(&self) -> WeakView<V> {
|
||||
Entity::downgrade(self)
|
||||
}
|
||||
|
||||
pub fn update<C, R>(
|
||||
&self,
|
||||
cx: &mut C,
|
||||
|
@ -111,8 +134,7 @@ pub struct WeakView<V> {
|
|||
|
||||
impl<V: 'static> WeakView<V> {
|
||||
pub fn upgrade(&self) -> Option<View<V>> {
|
||||
let model = self.model.upgrade()?;
|
||||
Some(View { model })
|
||||
Entity::upgrade_from(self)
|
||||
}
|
||||
|
||||
pub fn update<R>(
|
||||
|
@ -200,7 +222,7 @@ where
|
|||
}
|
||||
|
||||
fn entity_id(&self) -> EntityId {
|
||||
self.model.entity_id
|
||||
Entity::entity_id(self)
|
||||
}
|
||||
|
||||
fn model(&self) -> AnyModel {
|
||||
|
@ -208,7 +230,7 @@ where
|
|||
}
|
||||
|
||||
fn initialize(&self, cx: &mut WindowContext) -> AnyBox {
|
||||
cx.with_element_id(self.entity_id(), |_global_id, cx| {
|
||||
cx.with_element_id(ViewObject::entity_id(self), |_global_id, cx| {
|
||||
self.update(cx, |state, cx| {
|
||||
let mut any_element = Box::new(AnyElement::new(state.render(cx)));
|
||||
any_element.initialize(state, cx);
|
||||
|
@ -218,7 +240,7 @@ where
|
|||
}
|
||||
|
||||
fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
|
||||
cx.with_element_id(self.entity_id(), |_global_id, cx| {
|
||||
cx.with_element_id(ViewObject::entity_id(self), |_global_id, cx| {
|
||||
self.update(cx, |state, cx| {
|
||||
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
||||
element.layout(state, cx)
|
||||
|
@ -227,7 +249,7 @@ where
|
|||
}
|
||||
|
||||
fn paint(&self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
|
||||
cx.with_element_id(self.entity_id(), |_global_id, cx| {
|
||||
cx.with_element_id(ViewObject::entity_id(self), |_global_id, cx| {
|
||||
self.update(cx, |state, cx| {
|
||||
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
||||
element.paint(state, cx);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace,
|
||||
Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext, DisplayId, Edges, Effect,
|
||||
EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla,
|
||||
ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke, LayoutId,
|
||||
Entity, EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId,
|
||||
Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke, LayoutId,
|
||||
MainThread, MainThreadOnly, Model, ModelContext, Modifiers, MonochromeSprite, MouseButton,
|
||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformWindow,
|
||||
Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
|
||||
|
@ -1253,7 +1253,7 @@ impl Context for WindowContext<'_, '_> {
|
|||
self.entities.insert(slot, model)
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
model: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
|
@ -1568,23 +1568,25 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
|
|||
self.window_cx.on_next_frame(move |cx| view.update(cx, f));
|
||||
}
|
||||
|
||||
pub fn observe<E>(
|
||||
pub fn observe<V2, E>(
|
||||
&mut self,
|
||||
handle: &Model<E>,
|
||||
mut on_notify: impl FnMut(&mut V, Model<E>, &mut ViewContext<'_, '_, V>) + Send + 'static,
|
||||
entity: &E,
|
||||
mut on_notify: impl FnMut(&mut V, E, &mut ViewContext<'_, '_, V>) + Send + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
E: 'static,
|
||||
V2: 'static,
|
||||
V: Any + Send,
|
||||
E: Entity<V2>,
|
||||
{
|
||||
let view = self.view();
|
||||
let handle = handle.downgrade();
|
||||
let entity_id = entity.entity_id();
|
||||
let entity = entity.downgrade();
|
||||
let window_handle = self.window.handle;
|
||||
self.app.observers.insert(
|
||||
handle.entity_id,
|
||||
entity_id,
|
||||
Box::new(move |cx| {
|
||||
cx.update_window(window_handle.id, |cx| {
|
||||
if let Some(handle) = handle.upgrade() {
|
||||
if let Some(handle) = E::upgrade_from(&entity) {
|
||||
view.update(cx, |this, cx| on_notify(this, handle, cx))
|
||||
.is_ok()
|
||||
} else {
|
||||
|
@ -1596,21 +1598,24 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<E: EventEmitter>(
|
||||
pub fn subscribe<V2, E>(
|
||||
&mut self,
|
||||
handle: &Model<E>,
|
||||
mut on_event: impl FnMut(&mut V, Model<E>, &E::Event, &mut ViewContext<'_, '_, V>)
|
||||
+ Send
|
||||
+ 'static,
|
||||
) -> Subscription {
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(&mut V, E, &V2::Event, &mut ViewContext<'_, '_, V>) + Send + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
V2: EventEmitter,
|
||||
E: Entity<V2>,
|
||||
{
|
||||
let view = self.view();
|
||||
let handle = handle.downgrade();
|
||||
let entity_id = entity.entity_id();
|
||||
let handle = entity.downgrade();
|
||||
let window_handle = self.window.handle;
|
||||
self.app.event_listeners.insert(
|
||||
handle.entity_id,
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
cx.update_window(window_handle.id, |cx| {
|
||||
if let Some(handle) = handle.upgrade() {
|
||||
if let Some(handle) = E::upgrade_from(&handle) {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
view.update(cx, |this, cx| on_event(this, handle, event, cx))
|
||||
.is_ok()
|
||||
|
@ -1638,18 +1643,21 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn observe_release<T: 'static>(
|
||||
pub fn observe_release<V2, E>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
mut on_release: impl FnMut(&mut V, &mut T, &mut ViewContext<'_, '_, V>) + Send + 'static,
|
||||
entity: &E,
|
||||
mut on_release: impl FnMut(&mut V, &mut V2, &mut ViewContext<'_, '_, V>) + Send + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
V: Any + Send,
|
||||
V2: 'static,
|
||||
E: Entity<V2>,
|
||||
{
|
||||
let view = self.view();
|
||||
let entity_id = entity.entity_id();
|
||||
let window_handle = self.window.handle;
|
||||
self.app.release_listeners.insert(
|
||||
handle.entity_id,
|
||||
entity_id,
|
||||
Box::new(move |entity, cx| {
|
||||
let entity = entity.downcast_mut().expect("invalid entity type");
|
||||
let _ = cx.update_window(window_handle.id, |cx| {
|
||||
|
@ -1864,12 +1872,12 @@ impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> {
|
|||
self.window_cx.build_model(build_model)
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
model: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
|
||||
) -> R {
|
||||
self.window_cx.update_entity(model, update)
|
||||
self.window_cx.update_model(model, update)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ use futures::{
|
|||
};
|
||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||
use gpui2::{
|
||||
AnyModel, AppContext, AsyncAppContext, Context, EventEmitter, Executor, Model, ModelContext,
|
||||
Task, WeakModel,
|
||||
AnyModel, AppContext, AsyncAppContext, Context, Entity, EventEmitter, Executor, Model,
|
||||
ModelContext, Task, WeakModel,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language2::{
|
||||
|
@ -2491,7 +2491,7 @@ impl Project {
|
|||
delay
|
||||
} else {
|
||||
if first_insertion {
|
||||
let this = cx.weak_handle();
|
||||
let this = cx.weak_model();
|
||||
cx.defer(move |cx| {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| {
|
||||
|
@ -8650,7 +8650,7 @@ fn subscribe_for_copilot_events(
|
|||
// Another event wants to re-add the server that was already added and subscribed to, avoid doing it again.
|
||||
if !copilot_server.has_notification_handler::<copilot2::request::LogMessage>() {
|
||||
let new_server_id = copilot_server.server_id();
|
||||
let weak_project = cx.weak_handle();
|
||||
let weak_project = cx.weak_model();
|
||||
let copilot_log_subscription = copilot_server
|
||||
.on_notification::<copilot2::request::LogMessage, _>(
|
||||
move |params, mut cx| {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::Project;
|
||||
use gpui2::{AnyWindowHandle, Context, Model, ModelContext, WeakModel};
|
||||
use gpui2::{AnyWindowHandle, Context, Entity, Model, ModelContext, WeakModel};
|
||||
use settings2::Settings;
|
||||
use std::path::{Path, PathBuf};
|
||||
use terminal2::{
|
||||
|
|
Loading…
Reference in a new issue