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 GlobalActionCallback = dyn FnMut(&dyn AnyAction, &mut MutableAppContext);
|
||||||
|
|
||||||
type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
|
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 ObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
|
||||||
type ReleaseObservationCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
|
type ReleaseObservationCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
|
||||||
|
|
||||||
|
@ -757,6 +758,7 @@ pub struct MutableAppContext {
|
||||||
next_subscription_id: usize,
|
next_subscription_id: usize,
|
||||||
frame_count: usize,
|
frame_count: usize,
|
||||||
subscriptions: Arc<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>,
|
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>>>>,
|
observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ObservationCallback>>>>,
|
||||||
release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
|
release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
|
||||||
presenters_and_platform_windows:
|
presenters_and_platform_windows:
|
||||||
|
@ -804,6 +806,7 @@ impl MutableAppContext {
|
||||||
next_subscription_id: 0,
|
next_subscription_id: 0,
|
||||||
frame_count: 0,
|
frame_count: 0,
|
||||||
subscriptions: Default::default(),
|
subscriptions: Default::default(),
|
||||||
|
global_subscriptions: Default::default(),
|
||||||
observations: Default::default(),
|
observations: Default::default(),
|
||||||
release_observations: Default::default(),
|
release_observations: Default::default(),
|
||||||
presenters_and_platform_windows: HashMap::new(),
|
presenters_and_platform_windows: HashMap::new(),
|
||||||
|
@ -1062,6 +1065,12 @@ impl MutableAppContext {
|
||||||
self.foreground_platform.prompt_for_new_path(directory)
|
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
|
pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
|
||||||
where
|
where
|
||||||
E: Entity,
|
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
|
pub fn observe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
|
||||||
where
|
where
|
||||||
E: Entity,
|
E: Entity,
|
||||||
|
@ -1573,6 +1607,7 @@ impl MutableAppContext {
|
||||||
if let Some(effect) = self.pending_effects.pop_front() {
|
if let Some(effect) = self.pending_effects.pop_front() {
|
||||||
match effect {
|
match effect {
|
||||||
Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
|
Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
|
||||||
|
Effect::GlobalEvent { payload } => self.emit_global_event(payload),
|
||||||
Effect::ModelNotification { model_id } => {
|
Effect::ModelNotification { model_id } => {
|
||||||
self.notify_model_observers(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) {
|
fn notify_model_observers(&mut self, observed_id: usize) {
|
||||||
let callbacks = self.observations.lock().remove(&observed_id);
|
let callbacks = self.observations.lock().remove(&observed_id);
|
||||||
if let Some(callbacks) = callbacks {
|
if let Some(callbacks) = callbacks {
|
||||||
|
@ -2071,6 +2116,9 @@ pub enum Effect {
|
||||||
entity_id: usize,
|
entity_id: usize,
|
||||||
payload: Box<dyn Any>,
|
payload: Box<dyn Any>,
|
||||||
},
|
},
|
||||||
|
GlobalEvent {
|
||||||
|
payload: Box<dyn Any>,
|
||||||
|
},
|
||||||
ModelNotification {
|
ModelNotification {
|
||||||
model_id: usize,
|
model_id: usize,
|
||||||
},
|
},
|
||||||
|
@ -2104,6 +2152,10 @@ impl Debug for Effect {
|
||||||
.debug_struct("Effect::Event")
|
.debug_struct("Effect::Event")
|
||||||
.field("entity_id", entity_id)
|
.field("entity_id", entity_id)
|
||||||
.finish(),
|
.finish(),
|
||||||
|
Effect::GlobalEvent { payload, .. } => f
|
||||||
|
.debug_struct("Effect::GlobalEvent")
|
||||||
|
.field("type_id", &(&*payload).type_id())
|
||||||
|
.finish(),
|
||||||
Effect::ModelNotification { model_id } => f
|
Effect::ModelNotification { model_id } => f
|
||||||
.debug_struct("Effect::ModelNotification")
|
.debug_struct("Effect::ModelNotification")
|
||||||
.field("model_id", model_id)
|
.field("model_id", model_id)
|
||||||
|
@ -3762,6 +3814,11 @@ pub enum Subscription {
|
||||||
entity_id: usize,
|
entity_id: usize,
|
||||||
subscriptions: Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>>,
|
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 {
|
Observation {
|
||||||
id: usize,
|
id: usize,
|
||||||
entity_id: usize,
|
entity_id: usize,
|
||||||
|
@ -3781,6 +3838,9 @@ impl Subscription {
|
||||||
Subscription::Subscription { subscriptions, .. } => {
|
Subscription::Subscription { subscriptions, .. } => {
|
||||||
subscriptions.take();
|
subscriptions.take();
|
||||||
}
|
}
|
||||||
|
Subscription::GlobalSubscription { subscriptions, .. } => {
|
||||||
|
subscriptions.take();
|
||||||
|
}
|
||||||
Subscription::Observation { observations, .. } => {
|
Subscription::Observation { observations, .. } => {
|
||||||
observations.take();
|
observations.take();
|
||||||
}
|
}
|
||||||
|
@ -3794,6 +3854,28 @@ impl Subscription {
|
||||||
impl Drop for Subscription {
|
impl Drop for Subscription {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
match 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 {
|
Subscription::Observation {
|
||||||
id,
|
id,
|
||||||
entity_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();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WorkspaceBuilt(WeakViewHandle<Workspace>);
|
||||||
|
|
||||||
pub fn open_paths(
|
pub fn open_paths(
|
||||||
abs_paths: &[PathBuf],
|
abs_paths: &[PathBuf],
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
|
@ -1537,7 +1539,7 @@ pub fn open_paths(
|
||||||
}
|
}
|
||||||
|
|
||||||
let workspace = existing.unwrap_or_else(|| {
|
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(
|
let project = Project::local(
|
||||||
app_state.client.clone(),
|
app_state.client.clone(),
|
||||||
app_state.user_store.clone(),
|
app_state.user_store.clone(),
|
||||||
|
@ -1546,8 +1548,9 @@ pub fn open_paths(
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
(app_state.build_workspace)(project, &app_state, 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));
|
let task = workspace.update(cx, |workspace, cx| workspace.open_paths(abs_paths, cx));
|
||||||
|
@ -1581,12 +1584,13 @@ pub fn join_project(
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let (_, workspace) = cx.update(|cx| {
|
Ok(cx.update(|cx| {
|
||||||
cx.add_window((app_state.build_window_options)(), |cx| {
|
let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
|
||||||
(app_state.build_workspace)(project, &app_state, 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)
|
(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()));
|
cx.dispatch_action(window_id, vec![workspace.id()], &OpenNew(app_state.clone()));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue