mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-29 21:49:33 +00:00
Add global events to MutableAppContext and raise global event when new workspace is created
This commit is contained in:
parent
b62daebde1
commit
81fc812221
2 changed files with 95 additions and 19 deletions
|
@ -740,6 +740,7 @@ type ActionCallback =
|
|||
type GlobalActionCallback = dyn FnMut(&dyn AnyAction, &mut MutableAppContext);
|
||||
|
||||
type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
|
||||
type GlobalSubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
|
||||
type ObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
|
||||
type ReleaseObservationCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
|
||||
|
||||
|
@ -757,6 +758,7 @@ pub struct MutableAppContext {
|
|||
next_subscription_id: usize,
|
||||
frame_count: usize,
|
||||
subscriptions: Arc<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>,
|
||||
global_subscriptions: Arc<Mutex<HashMap<TypeId, BTreeMap<usize, GlobalSubscriptionCallback>>>>,
|
||||
observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ObservationCallback>>>>,
|
||||
release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
|
||||
presenters_and_platform_windows:
|
||||
|
@ -804,6 +806,7 @@ impl MutableAppContext {
|
|||
next_subscription_id: 0,
|
||||
frame_count: 0,
|
||||
subscriptions: Default::default(),
|
||||
global_subscriptions: Default::default(),
|
||||
observations: Default::default(),
|
||||
release_observations: Default::default(),
|
||||
presenters_and_platform_windows: HashMap::new(),
|
||||
|
@ -1062,6 +1065,12 @@ impl MutableAppContext {
|
|||
self.foreground_platform.prompt_for_new_path(directory)
|
||||
}
|
||||
|
||||
pub fn emit_global<E: Any>(&mut self, payload: E) {
|
||||
self.pending_effects.push_back(Effect::GlobalEvent {
|
||||
payload: Box::new(payload),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
|
||||
where
|
||||
E: Entity,
|
||||
|
@ -1075,6 +1084,31 @@ impl MutableAppContext {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn global_subscribe<E, F>(&mut self, mut callback: F) -> Subscription
|
||||
where
|
||||
E: Any + Copy,
|
||||
F: 'static + FnMut(&E, &mut Self),
|
||||
{
|
||||
let id = post_inc(&mut self.next_subscription_id);
|
||||
let type_id = TypeId::of::<E>();
|
||||
self.global_subscriptions
|
||||
.lock()
|
||||
.entry(type_id)
|
||||
.or_default()
|
||||
.insert(
|
||||
id,
|
||||
Box::new(move |payload, cx| {
|
||||
let payload = payload.downcast_ref().expect("downcast is type safe");
|
||||
callback(payload, cx)
|
||||
}));
|
||||
Subscription::GlobalSubscription {
|
||||
id,
|
||||
type_id,
|
||||
subscriptions: Some(Arc::downgrade(&self.global_subscriptions))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn observe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
|
||||
where
|
||||
E: Entity,
|
||||
|
@ -1573,6 +1607,7 @@ impl MutableAppContext {
|
|||
if let Some(effect) = self.pending_effects.pop_front() {
|
||||
match effect {
|
||||
Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
|
||||
Effect::GlobalEvent { payload } => self.emit_global_event(payload),
|
||||
Effect::ModelNotification { model_id } => {
|
||||
self.notify_model_observers(model_id)
|
||||
}
|
||||
|
@ -1700,6 +1735,16 @@ impl MutableAppContext {
|
|||
}
|
||||
}
|
||||
|
||||
fn emit_global_event(&mut self, payload: Box<dyn Any>) {
|
||||
let type_id = (&*payload).type_id();
|
||||
let callbacks = self.global_subscriptions.lock().remove(&type_id);
|
||||
if let Some(callbacks) = callbacks {
|
||||
for (_, mut callback) in callbacks {
|
||||
callback(payload.as_ref(), self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_model_observers(&mut self, observed_id: usize) {
|
||||
let callbacks = self.observations.lock().remove(&observed_id);
|
||||
if let Some(callbacks) = callbacks {
|
||||
|
@ -2071,6 +2116,9 @@ pub enum Effect {
|
|||
entity_id: usize,
|
||||
payload: Box<dyn Any>,
|
||||
},
|
||||
GlobalEvent {
|
||||
payload: Box<dyn Any>,
|
||||
},
|
||||
ModelNotification {
|
||||
model_id: usize,
|
||||
},
|
||||
|
@ -2104,6 +2152,10 @@ impl Debug for Effect {
|
|||
.debug_struct("Effect::Event")
|
||||
.field("entity_id", entity_id)
|
||||
.finish(),
|
||||
Effect::GlobalEvent { payload, .. } => f
|
||||
.debug_struct("Effect::GlobalEvent")
|
||||
.field("type_id", &(&*payload).type_id())
|
||||
.finish(),
|
||||
Effect::ModelNotification { model_id } => f
|
||||
.debug_struct("Effect::ModelNotification")
|
||||
.field("model_id", model_id)
|
||||
|
@ -3762,6 +3814,11 @@ pub enum Subscription {
|
|||
entity_id: usize,
|
||||
subscriptions: Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>>,
|
||||
},
|
||||
GlobalSubscription {
|
||||
id: usize,
|
||||
type_id: TypeId,
|
||||
subscriptions: Option<Weak<Mutex<HashMap<TypeId, BTreeMap<usize, GlobalSubscriptionCallback>>>>>,
|
||||
},
|
||||
Observation {
|
||||
id: usize,
|
||||
entity_id: usize,
|
||||
|
@ -3781,6 +3838,9 @@ impl Subscription {
|
|||
Subscription::Subscription { subscriptions, .. } => {
|
||||
subscriptions.take();
|
||||
}
|
||||
Subscription::GlobalSubscription { subscriptions, .. } => {
|
||||
subscriptions.take();
|
||||
}
|
||||
Subscription::Observation { observations, .. } => {
|
||||
observations.take();
|
||||
}
|
||||
|
@ -3794,6 +3854,28 @@ impl Subscription {
|
|||
impl Drop for Subscription {
|
||||
fn drop(&mut self) {
|
||||
match self {
|
||||
Subscription::Subscription {
|
||||
id,
|
||||
entity_id,
|
||||
subscriptions,
|
||||
} => {
|
||||
if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
|
||||
if let Some(subscriptions) = subscriptions.lock().get_mut(entity_id) {
|
||||
subscriptions.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Subscription::GlobalSubscription {
|
||||
id,
|
||||
type_id,
|
||||
subscriptions,
|
||||
} => {
|
||||
if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
|
||||
if let Some(subscriptions) = subscriptions.lock().get_mut(type_id) {
|
||||
subscriptions.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Subscription::Observation {
|
||||
id,
|
||||
entity_id,
|
||||
|
@ -3816,17 +3898,6 @@ impl Drop for Subscription {
|
|||
}
|
||||
}
|
||||
}
|
||||
Subscription::Subscription {
|
||||
id,
|
||||
entity_id,
|
||||
subscriptions,
|
||||
} => {
|
||||
if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
|
||||
if let Some(subscriptions) = subscriptions.lock().get_mut(entity_id) {
|
||||
subscriptions.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1511,6 +1511,8 @@ fn open(action: &Open, cx: &mut MutableAppContext) {
|
|||
.detach();
|
||||
}
|
||||
|
||||
pub struct WorkspaceBuilt(WeakViewHandle<Workspace>);
|
||||
|
||||
pub fn open_paths(
|
||||
abs_paths: &[PathBuf],
|
||||
app_state: &Arc<AppState>,
|
||||
|
@ -1537,7 +1539,7 @@ pub fn open_paths(
|
|||
}
|
||||
|
||||
let workspace = existing.unwrap_or_else(|| {
|
||||
cx.add_window((app_state.build_window_options)(), |cx| {
|
||||
let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
|
||||
let project = Project::local(
|
||||
app_state.client.clone(),
|
||||
app_state.user_store.clone(),
|
||||
|
@ -1546,8 +1548,9 @@ pub fn open_paths(
|
|||
cx,
|
||||
);
|
||||
(app_state.build_workspace)(project, &app_state, cx)
|
||||
})
|
||||
.1
|
||||
});
|
||||
cx.emit_global(WorkspaceBuilt(workspace.downgrade()));
|
||||
workspace
|
||||
});
|
||||
|
||||
let task = workspace.update(cx, |workspace, cx| workspace.open_paths(abs_paths, cx));
|
||||
|
@ -1581,12 +1584,13 @@ pub fn join_project(
|
|||
&mut cx,
|
||||
)
|
||||
.await?;
|
||||
let (_, workspace) = cx.update(|cx| {
|
||||
cx.add_window((app_state.build_window_options)(), |cx| {
|
||||
Ok(cx.update(|cx| {
|
||||
let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
|
||||
(app_state.build_workspace)(project, &app_state, cx)
|
||||
})
|
||||
});
|
||||
Ok(workspace)
|
||||
});
|
||||
cx.emit_global(WorkspaceBuilt(workspace.downgrade()));
|
||||
workspace
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1601,5 +1605,6 @@ fn open_new(app_state: &Arc<AppState>, cx: &mut MutableAppContext) {
|
|||
);
|
||||
(app_state.build_workspace)(project, &app_state, cx)
|
||||
});
|
||||
cx.emit_global(WorkspaceBuilt(workspace.downgrade()));
|
||||
cx.dispatch_action(window_id, vec![workspace.id()], &OpenNew(app_state.clone()));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue