Send pane `removeItem` event before removing the item (#15541)

Remco Smits created

This PR renames and added a new pane event to indicate the difference
between `removing` and `removed` event. This change is needed for the
debugger implementation, if you close a pane we have to send a
`terminateThread` request to the adapter because it's not supported to
reopen a pane. So when the pane is removing we have to know what thread
it is what is stored on the panel itself, so we have to be able to get
this information before the pane is actually removed.

So my idea how to fix this was by adding a new event called
`RemovedItem` which is a rename of `RemoveItem` which also makes a bit
more sense because the item is removed at that point. And seeing the
name `RemoveItem` does not really say that it's removed, more like we
are removing the item.

/cc @mikayla-maki

Release Notes:

- N/A

Change summary

crates/assistant/src/assistant_panel.rs    |  2 +-
crates/tab_switcher/src/tab_switcher.rs    |  2 +-
crates/terminal_view/src/terminal_panel.rs |  2 +-
crates/workspace/src/pane.rs               | 12 ++++++++----
crates/workspace/src/workspace.rs          |  3 ++-
5 files changed, 13 insertions(+), 8 deletions(-)

Detailed changes

crates/assistant/src/assistant_panel.rs 🔗

@@ -465,7 +465,7 @@ impl AssistantPanel {
                 true
             }
 
-            pane::Event::RemoveItem { .. } => {
+            pane::Event::RemovedItem { .. } => {
                 cx.emit(AssistantPanelEvent::ContextEdited);
                 true
             }

crates/tab_switcher/src/tab_switcher.rs 🔗

@@ -173,7 +173,7 @@ impl TabSwitcherDelegate {
         };
         cx.subscribe(&pane, |tab_switcher, _, event, cx| {
             match event {
-                PaneEvent::AddItem { .. } | PaneEvent::RemoveItem { .. } | PaneEvent::Remove => {
+                PaneEvent::AddItem { .. } | PaneEvent::RemovedItem { .. } | PaneEvent::Remove => {
                     tab_switcher.picker.update(cx, |picker, cx| {
                         let selected_item_id = picker.delegate.selected_item_id();
                         picker.delegate.update_matches(cx);

crates/terminal_view/src/terminal_panel.rs 🔗

@@ -342,7 +342,7 @@ impl TerminalPanel {
     ) {
         match event {
             pane::Event::ActivateItem { .. } => self.serialize(cx),
-            pane::Event::RemoveItem { .. } => self.serialize(cx),
+            pane::Event::RemovedItem { .. } => self.serialize(cx),
             pane::Event::Remove => cx.emit(PanelEvent::Close),
             pane::Event::ZoomIn => cx.emit(PanelEvent::ZoomIn),
             pane::Event::ZoomOut => cx.emit(PanelEvent::ZoomOut),

crates/workspace/src/pane.rs 🔗

@@ -169,7 +169,8 @@ pub enum Event {
     AddItem { item: Box<dyn ItemHandle> },
     ActivateItem { local: bool },
     Remove,
-    RemoveItem { item_id: EntityId },
+    RemoveItem { idx: usize },
+    RemovedItem { item_id: EntityId },
     Split(SplitDirection),
     ChangeItemTitle,
     Focus,
@@ -189,8 +190,9 @@ impl fmt::Debug for Event {
                 .field("local", local)
                 .finish(),
             Event::Remove => f.write_str("Remove"),
-            Event::RemoveItem { item_id } => f
-                .debug_struct("RemoveItem")
+            Event::RemoveItem { idx } => f.debug_struct("RemoveItem").field("idx", idx).finish(),
+            Event::RemovedItem { item_id } => f
+                .debug_struct("RemovedItem")
                 .field("item_id", item_id)
                 .finish(),
             Event::Split(direction) => f
@@ -1302,9 +1304,11 @@ impl Pane {
             }
         }
 
+        cx.emit(Event::RemoveItem { idx: item_index });
+
         let item = self.items.remove(item_index);
 
-        cx.emit(Event::RemoveItem {
+        cx.emit(Event::RemovedItem {
             item_id: item.item_id(),
         });
         if self.items.is_empty() {

crates/workspace/src/workspace.rs 🔗

@@ -2903,7 +2903,8 @@ impl Workspace {
                 }
                 self.update_window_edited(cx);
             }
-            pane::Event::RemoveItem { item_id } => {
+            pane::Event::RemoveItem { .. } => {}
+            pane::Event::RemovedItem { item_id } => {
                 cx.emit(Event::ActiveItemChanged);
                 self.update_window_edited(cx);
                 if let hash_map::Entry::Occupied(entry) = self.panes_by_item.entry(*item_id) {