From a8f6522e91f3491e2006a9502e0c72a30dc5da0c Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 17 May 2026 08:26:19 +0200 Subject: [PATCH] Count document tabs globally for closable splits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UpdateLastDocumentCanClose was counting only factory.Documents.VisibleDockables to decide CanClose. After the user drags a tab out into a side-by-side split, Dock creates a second IDocumentDock that holds the dragged tab. factory.Documents still points at the ORIGINAL dock (now with one tab), so the handler updates CanClose=false on its remaining tab — but the new sibling dock's tab keeps the CanClose=true it had before the drag. Result: one tab closable, the other not, even though the user has two documents open. Assisted-by: Claude:claude-opus-4-7:Claude Code --- ILSpy/Docking/DockWorkspace.cs | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index 980ca4bc2..4c6e3c50a 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -267,17 +267,36 @@ namespace ILSpy.Docking } } - // When only one document is open, make it un-closeable so the user can't end up with an - // empty document area. + // When only one document is open across the entire workspace, make it un-closeable so + // the user can't end up with an empty document area. Counts across ALL IDocumentDocks + // in the layout tree — not just factory.Documents — so a split into side-by-side + // document docks (each with one tab) still lets the user close either one. void UpdateLastDocumentCanClose() { - var docs = factory.Documents?.VisibleDockables; - if (docs == null) + if (Layout is not IDockable root) return; - bool canClose = docs.Count > 1; - foreach (var d in docs) + var allDocs = FlattenDocumentDocks(root).ToList(); + int totalTabs = allDocs.Sum(d => d.VisibleDockables?.Count ?? 0); + bool canClose = totalTabs > 1; + foreach (var dock in allDocs) + { + if (dock.VisibleDockables is { } kids) + { + foreach (var d in kids) + d.CanClose = canClose; + } + } + } + + static IEnumerable FlattenDocumentDocks(IDockable root) + { + if (root is IDocumentDock doc) + yield return doc; + if (root is IDock dock && dock.VisibleDockables is { } kids) { - d.CanClose = canClose; + foreach (var k in kids) + foreach (var d in FlattenDocumentDocks(k)) + yield return d; } }