From 774cef5cb061d48d15602ca7957d88f5cdad9757 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 6 Jun 2026 23:15:01 +0200 Subject: [PATCH] Restore Close entries on the document-tab context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The freeze work pointed Dock's DocumentContextMenu (which it shows on a document-tab right-click, overriding the standard ContextMenu) at a menu holding only "Freeze tab". That hid the Close / Close all but this / Close all entries defined in App.axaml, and on a frozen tab — where the Freeze item is hidden — the whole menu came up empty. Build the full menu (Close / Close all but this / Close all, plus the preview-only Freeze entry) in PreviewTabContextMenuBehavior and drop the now-superseded App.axaml ContextMenu setter, so there is a single source for the document-tab menu. Assisted-by: Claude:claude-opus-4-8:Claude Code --- .../Docking/DocumentTabContextMenuTests.cs | 28 +++++++++++ .../Docking/PreviewTabPromotionTests.cs | 8 +-- ILSpy/App.axaml | 16 ++---- ILSpy/Themes/PreviewTabContextMenuBehavior.cs | 49 +++++++++++++++---- 4 files changed, 75 insertions(+), 26 deletions(-) diff --git a/ILSpy.Tests/Docking/DocumentTabContextMenuTests.cs b/ILSpy.Tests/Docking/DocumentTabContextMenuTests.cs index 631bc59cc..567fe6707 100644 --- a/ILSpy.Tests/Docking/DocumentTabContextMenuTests.cs +++ b/ILSpy.Tests/Docking/DocumentTabContextMenuTests.cs @@ -51,6 +51,34 @@ public class DocumentTabContextMenuTests return (a, b, c); } + [AvaloniaTest] + public async Task Menu_Carries_The_Close_Entries_Bound_To_The_Tab_Commands() + { + // Regression: the per-tab DocumentContextMenu (which Dock shows, overriding the standard + // ContextMenu) once held only "Freeze tab", so the Close / Close all entries went missing + // (and the whole menu was empty on a frozen tab). It must carry all three close entries. + var window = AppComposition.Current.GetExport(); + window.Show(); + var vm = (MainWindowViewModel)window.DataContext!; + await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); + var (a, _, _) = OpenThreeTabs(vm.DockWorkspace); + + var menu = global::ILSpy.Themes.PreviewTabContextMenuBehavior.BuildDocumentContextMenu(a); + var items = menu.ItemsSource!.OfType().ToList(); + + items.Select(m => m.Header).Should().Contain(new object[] { + ICSharpCode.ILSpy.Properties.Resources.Close, + ICSharpCode.ILSpy.Properties.Resources.CloseAllButThisTab, + ICSharpCode.ILSpy.Properties.Resources.CloseAllTabs, + }); + items.Single(m => Equals(m.Header, ICSharpCode.ILSpy.Properties.Resources.Close)).Command + .Should().BeSameAs(a.CloseCommand); + items.Single(m => Equals(m.Header, ICSharpCode.ILSpy.Properties.Resources.CloseAllButThisTab)).Command + .Should().BeSameAs(a.CloseAllButThisCommand); + items.Single(m => Equals(m.Header, ICSharpCode.ILSpy.Properties.Resources.CloseAllTabs)).Command + .Should().BeSameAs(a.CloseAllCommand); + } + [AvaloniaTest] public async Task Close_All_But_This_Leaves_Only_The_Target_Tab() { diff --git a/ILSpy.Tests/Docking/PreviewTabPromotionTests.cs b/ILSpy.Tests/Docking/PreviewTabPromotionTests.cs index 992d28561..6f0730b15 100644 --- a/ILSpy.Tests/Docking/PreviewTabPromotionTests.cs +++ b/ILSpy.Tests/Docking/PreviewTabPromotionTests.cs @@ -415,11 +415,13 @@ public class PreviewTabPromotionTests var carveOutItem = window.GetVisualDescendants().OfType() .Single(item => item.DataContext is ContentTabPage t && t.SourceNode == typeNode); - var mainFreezeEntry = mainTabItem.DocumentContextMenu!.Items.OfType().Single(); - mainFreezeEntry.Header.Should().Be("Freeze tab"); + // The menu now also carries Close / Close all but this / Close all; pick the Freeze entry. + var mainFreezeEntry = mainTabItem.DocumentContextMenu!.Items.OfType() + .Single(m => (string?)m.Header == "Freeze tab"); mainFreezeEntry.IsVisible.Should().BeTrue("MainTab is preview — Freeze tab entry must be visible"); - var carveFreezeEntry = carveOutItem.DocumentContextMenu!.Items.OfType().Single(); + var carveFreezeEntry = carveOutItem.DocumentContextMenu!.Items.OfType() + .Single(m => (string?)m.Header == "Freeze tab"); carveFreezeEntry.IsVisible.Should().BeFalse( "carve-out tabs are already frozen — the Freeze entry must hide"); } diff --git a/ILSpy/App.axaml b/ILSpy/App.axaml index 6fe340b96..addac8231 100644 --- a/ILSpy/App.axaml +++ b/ILSpy/App.axaml @@ -306,19 +306,9 @@ names, so this is document-only. -->