diff --git a/src/tabs/tab.rs b/src/tabs/tab.rs index 89c71288..91821c42 100644 --- a/src/tabs/tab.rs +++ b/src/tabs/tab.rs @@ -83,19 +83,65 @@ where pub fn clean_tabs bool>(&self, mut f: F) { let mut i = 0; let mut state = self.state.lock(); + + let focused_id = state.find_active_focused().map(|(_, tab)| tab.id()); + let mut active_tab = None; + loop { let Some(surface) = state.get_surface_mut(egui_dock::SurfaceIndex(i)) else { break; }; + if let Some(tree) = surface.node_tree_mut() { - for node in tree.iter_mut() { + let mut is_empty = !egui_dock::SurfaceIndex(i).is_main(); + + for (j, node) in tree.iter_mut().enumerate() { if let egui_dock::Node::Leaf { tabs, .. } = node { tabs.retain_mut(&mut f); + + if !tabs.is_empty() { + is_empty = false; + } + + // Check if the originally focused tab is inside this tree + if let Some(k) = focused_id.and_then(|id| { + tabs.iter().enumerate().find_map(|(i, tab)| { + if tab.id() == id { + Some(i) + } else { + None + } + }) + }) { + active_tab = Some((i, j, k)); + } } } + + // We need to remove empty windows or we'll cause a crash + if is_empty { + state.remove_surface(egui_dock::SurfaceIndex(i)); + } } i += 1; } + + // If the previously focused tab hasn't been removed, refocus it since the index may have + // changed, otherwise the application may crash due to out-of-bounds vector access + if let Some((i, j, k)) = active_tab { + state.set_active_tab(( + egui_dock::SurfaceIndex(i), + egui_dock::NodeIndex(j), + egui_dock::TabIndex(k), + )); + } + // Otherwise we need to unfocus all tabs, again to prevent a crash + else { + state.set_focused_node_and_surface(( + egui_dock::SurfaceIndex(usize::MAX), + egui_dock::NodeIndex(usize::MAX), + )); + } } /// Returns the name of the focused tab.